我有一个文件,有多个记录,每个记录都有多个字段。文件内容如下。
# cat inputfile
name: AAA
age: 38
city: C1
state: S1
age: 29
city: C2
name: BBBbbbB
state: S2
state: S3
age: 21
city: C3
name: ccccccC
我想按照 shell 脚本的参数给出的顺序对每个记录的字段进行排序。
如果我运行如下脚本:
# sh sortout.sh <inputfile> name age city state
输出应如下所示:
name: AAA
age: 38
city: C1
state: S1
name: BBBbbbB
age: 29
city: C2
state: S2
name: ccccccC
age: 21
city: C3
state: S3
答案1
当Perl
您在段落模式下操作时,这意味着让 perl 使用该选项一次吞掉一个段落-00
。
然后从当前记录中获取第一个字段(以冒号分隔)并存储在哈希中。
$ perl -l -00ane '
my %h = reverse /^(([^:]+):.*)$/mg;
print $h{$_} for qw/name age city state/;
' input.file
根据您的具体要求,您可以这样做:
cat - <<\eof > code.sh
if=$1;shift
perl -ls -00ane '
my %h = reverse /^(([^:]+):.*)$/mg;
print $h{$_} for split /\s+/, $order;
' -- -order="$*" "$if"
eof
创建代码文件后,执行它:
sh code.sh inputfile name age city state
答案2
由于您不了解 Perl,所以我会稍微冗长一些。
首先,Perl 是一个 Linux 实用程序,它获取输入文件并通过其命令进行转换,以生成所需的输出。
通常 Perl 一次检查输入文件一行。一行与下一行通过 ascii 字符\012
(也\n
称为换行符)分隔开。但在这种情况下,我们宁愿一次阅读一个段落。 Perl 如何识别para?
-00
选项将处理段落。它们存储在当前记录标量中$_
请注意,一条记录现在应包含多行。
我将其想象为:
^....$ ^...$ ^....$
基本上是连续的线条岛。这些岛屿均由 \n 分隔。
使用的 Perl 选项:
-l
这做了两件事,从当前记录 $_ 中删除输入记录分隔符,并在打印时将其放回原处:
$/ = $\ = "\n"
-s
这将打开基本的命令行开关解析。有了它,我们可以从命令行本身指定要打印变量的顺序。
-00
是 IRS 分隔符设置为段落模式 = 空字符串。这将从输入数据中一次提取一个段落,并将其存储在$_
for 每次迭代中。
-n
这会在文件周围放置一个循环,这意味着它将从输入文件(实际上是一个文件句柄,但这对我们的级别来说并不重要)读取,但当转换全部应用于当前记录时,不会在最后打印它。你必须明确地这样做。
-e
该选项告诉 perl 后面的内容是将应用于当前记录的有效 Perl 代码。
--
=>Perl 命令行选项的结尾,接下来是开关(以破折号开头),然后是文件。如果您的文件名可能以破折号开头,最好以 ./ 开头,或者给出完整或相对路径,或者再放置一个--
以表示开关结束。
现在是algorithm
部分:
my %h = reverse /^(([^:]+):. *)$/mg;
%
在 Perl 中,散列或关联数组在其名称前用百分比来标识。因此,在我们的例子中,我们正在构建一个散列%h
,并在其前面放置一个my
,这意味着它将是词法的,并且每当读入下一条记录时就会退出 if 范围。这意味着,将为每个记录创建一个全新的散列。
这个表达是什么/..../mg
意思?首先,所有正则表达式始终通过 if 运算符与某个标量变量或表达式相关联=~
。但在这里我们没有看到一个。它隐式地与变量绑定在一起$_
,这意味着当前记录。
待续 - -