Perl单行命令 四 - Numbering

注:该文写作来自于 perl-one-liners-explained 这本书,感兴趣的童鞋可以搜索,然后去购买,大概 9 美元还是多少来着。该作者还有 awk 和 sed 系列的单行命令书。

以上所有的测试都以这个test.pl为准

#!/usr/bin/perl
use strict;
use List::MoreUtils qw(uniq);
#use Data::Dumper;
open(FD,"1.txt")||die("Can not open the file!$!n");
my $line;
while($line=<FD>){
 chomp;
 my @log=split(/####/,$line);
 $log[3] =~ s/ *$//;
 if ($log[3] eq '' ) {
 print "insert into 2car_query ( date,ip,mode,querytime) values ( \'$log[0]\',\'$log[1]\',\'$log[2]\',\'$log[4]\');\n";
 }else {
 my @operation=split(/\&/,$log[3]);
 @operation= uniq @operation;
 my %hash;
 foreach (@operation) {
 chomp;
 my @tmp = split (/\=/,$_);
 $hash{$tmp[0]} = $tmp[1];
 }
 while (my ($key, $value) = each(%hash)) {
 print "$key => $value\n";
 push @key,$key;
 push @value,$value;
 }
 foreach (@key) {
 if (s/year/year1/) {
 last;
 }
 my $key_new= join ",",@key;
 my $value_new = join '\',\'',@value;
 print "insert into 2car_query ( date,ip,mode,querytime,$key) values ( \'$log[0]\',\'$log[1]\',\'$log[2]\',\'$log[4]\',\'$value\');\n"
 }
}%

给一个文件中的所有行编号

perl -pe '$_ = "$. $_"' test.pl

结果为:

1 #!/usr/bin/perl
2 use strict;
3 use List::MoreUtils qw(uniq);
4 #use Data::Dumper;
5 open(FD,"1.txt")||die("Can not open the file!$!n");
6
7 my $line;
8 while($line=<FD>){
9 chomp;
10
11 my @log=split(/####/,$line);
12 $log[3] =~ s/ *$//;
13 if ($log[3] eq '' ) {
14 print "insert into 2car_query ( date,ip,mode,querytime) values ( \'$log[0]\',\'$log[1]\',\'$log[2]\',\'$log[4]\');\n";
15 }else {
16 my @operation=split(/\&/,$log[3]);
17 @operation= uniq @operation;
18
19 my %hash;
20 foreach (@operation) {
21 chomp;
22 my @tmp = split (/\=/,$_);
23
24 $hash{$tmp[0]} = $tmp[1];
25
26
27 }
28 while (my ($key, $value) = each(%hash)) {
29
30 print "$key => $value\n";
31 push @key,$key;
32 push @value,$value;
33 }
34 foreach (@key) {
35 if (s/year/year1/) {
36 last;
37 }
38 my $key_new= join ",",@key;
39 my $value_new = join '\',\'',@value;
40 print "insert into 2car_query ( date,ip,mode,querytime,$key) values ( \'$log[0]\',\'$log[1]\',\'$log[2]\',\'$log[4]\',\'$value\');\n"
41 }
42 }%

其中会把空行也编号,在这条语句中 -p 参数的作用是相当于对 test.pl 做循环处理并且打印。-e 就是把后面的作为一个 perl 程序执行。 $. 表示行号。 $_ 表示当前处理行。上面这行程序的意思就是把 $.$_的值赋给 $_变量,然后输出,结果就如上,即行号+程序内容

仅仅只给文件中的非空行编号

perl -pe '$_ = ++$a." $_" if /./' test.pl

得出的结果如下:

1 #!/usr/bin/perl
2 use strict;
3 use List::MoreUtils qw(uniq);
4 #use Data::Dumper;
5 open(FD,"1.txt")||die("Can not open the file!$!n");
6 my $line;
7 while($line=<FD>){
8 chomp;
9 my @log=split(/####/,$line);
10 $log[3] =~ s/ *$//;
11 if ($log[3] eq '' ) {

可以看到编号5和编号6之间的空行未被编号。这里我们使用 if 条件语句来作判断,当 if 中的条件为真时,就执行 $_ = ++$a." $_" 这个命令,为假时,就不执行,这个命令行中的 if 的判断语句 /./ 作用就是匹配文件中的任何字符,换行除外(即空行除外),这个 ++$a 表示的是非空行,当条件匹配的时候非空行自加,其中 $a 后面的 . 表示的是连接符。

在一个文件中,仅仅编号和打印非空行

perl -ne 'print ++$a." $_" if /./' test.pl

输出结果如下:

 #!/usr/bin/perl
2 use strict;
3 use List::MoreUtils qw(uniq);
4 #use Data::Dumper;
5 open(FD,"1.txt")||die("Can not open the file!$!n");
6 my $line;
7 while($line=<FD>){
8 chomp;
9 my @log=split(/####/,$line);
10 $log[3] =~ s/ *$//;
11 if ($log[3] eq '' ) {

可以看到,空行未输出。
其中命令参数 -n 的作用不像 -p 那样有打印输出功能,因此在这个语句中必须要使用 print 命令来输出内容。因为这个print不是对程序循环打印的,只是在匹配的时候打印下,因此输出的都是匹配到的非空行。

在一个文件中,编号所有行,但是仅仅打印非空行

perl -pe '$_ = "$. $_" if /./' test.pl

输出的结果如下:

1 #!/usr/bin/perl
2 use strict;
3 use List::MoreUtils qw(uniq);
4 #use Data::Dumper;
5 open(FD,"1.txt")||die("Can not open the file!$!n");
7 my $line;
8 while($line=<FD>){
9 chomp;

其中,空行也给标记了。因为这个没有对非空行做自增。

给符合模式匹配的行编号,并且打印其他未作编号的

perl -pe '$_ = ++$a." $_" if /#/' test.pl

结果为:

1 #!/usr/bin/perl
use strict;
use List::MoreUtils qw(uniq);
2 #use Data::Dumper;
open(FD,"1.txt")||die("Can not open the file!$!n");
my $line;
while($line=<FD>){
 chomp;
3 my @log=split(/####/,$line);

编号并且打印那些仅仅符合模式匹配的行

perl -ne 'print ++$a." $_" if /#/' test.pl

结果为:

1 #!/usr/bin/perl
2 #use Data::Dumper;
3 my @log=split(/####/,$line);

用经典格式输出编号所有行

perl -ne 'printf "%-5d %s", $., $_' test.pl

结果为:

1 #!/usr/bin/perl
2 use strict;
3 use List::MoreUtils qw(uniq);
4 #use Data::Dumper;
5 open(FD,"1.txt")||die("Can not open the file!$!n");
6
7 my $line;
8 while($line=<FD>){
9 chomp;

打印一个文件的总行数(相当于 wc -l)

perl -lne 'END { print $. }' test.pl

结果为:

42

对用 wc -l ```` 和 上面这个对比了下计算性能,wc -l``` 更加消耗 cpu ,而上面的语句执行时间更长点。各位有兴趣的可以拿几个 G 的文件计算对比下。

这个 END 块是 perl 从 AWK 参考的而来的一个特性。这个 END 块会再程序执行完成后再生效。参数 -l 的作用是通过使用一个换行为输出的记录做分割用,这样我们就不用使用 “$.\n” 了。
还有一个类似的做法是

perl -le 'print $n=()=<>' test.pl

这是一个比较有技巧的命令行。如果你知道 perl 的上下文的概念的话,就非常容易理解了。在这个命令行中 ()=<> 这个引起了钻石操作符被转换成列表上下文。它让钻石操作符把整个文件读取进了一个列表。然后我们把列表分配给变量 $n,因为 $n 是一个标量,因此列表上下文被转换成标量上下文。把列表上下文转换成标量上下文的结果是返回列表的元素数量。因此 $n=()=<> 等于文件的行数。同时这个也和如下语句很像:

perl -le 'print scalar(()=<>)' test.pl

还有如下也是一样的:

perl -ne '}{print $.' test.pl

参数 -n 的作用相当于一个 while(<>) { }循环处理程序。而 }{ 操作符(eskimo operator 这个不知道咋翻译。)的作用就是跳出这个循环,相当于如下语句:

while (<>) {
}{ # eskimo operator here
print $.;
}

打印文件中非空行的行数

perl -le 'print scalar(grep{/./}<>)' test.pl

结果为:

37

打印文件中空行的行数

perl -lne '$a++ if /^$/; END {print $a+0}' test.pl

结果为:

5

我们还可以把程序修改成

perl -le 'print scalar(grep{/^$/}<>)' test.pl

还可以用 ~~:

perl -le 'print ~~grep{/^$/}<>' test.pl

这个操作符相当于做了两次位移操作,使 grep 在标量上下文中被执行

注:后面这两个版本不是非常高效的,它使把整个文件读取进内存来操作的。第一个版本是一行行的读取。

打印文件中符合匹配模式的行数(等价与 grep -c)

perl -lne '$a++ if /regex/; END {print $a+0}' test.pl

给所有行标记单词数(打印出来好杂乱)

perl -pe 's/(\w+)/++$i.".$1"/ge' test.pl

部分结果为:

#!/1.usr/2.bin/3.perl
4.use 5.strict;
6.use 7.List::8.MoreUtils 9.qw(10.uniq);
#11.use 12.Data::13.Dumper;
14.open(15.FD,"16.1.17.txt")||18.die("19.Can 20.not 21.open 22.the 23.file!$!24.n");
25.my $26.line;
27.while($28.line=<29.FD>){
 30.chomp;

这个 e 的参数的作用是让 perl 把 s/match/repl/ 表达式作为代码运行。g 表示全局的意思。$1 就是等于 \w+ 匹配到的结果。

每行独立的打印单词数

perl -pe '$i=0; s/(\w+)/++$i.".$1"/ge' test.pl

部分结果为:

#!/1.usr/2.bin/3.perl
1.use 2.strict;
1.use 2.List::3.MoreUtils 4.qw(5.uniq);
#1.use 2.Data::3.Dumper;
1.open(2.FD,"3.1.4.txt")||5.die("6.Can 7.not 8.open 9.the 10.file!$!11.n");
1.my $2.line;
1.while($2.line=<3.FD>){
 1.chomp;

用他们数字的位置替换所有的单词

perl -pe 's/(\w+)/++$i/ge' test.pl

部分结果如下:

#!/1/2/3
4 5;
6 7::8 9(10);
#11 12::13;
14(15,"16.17")||18("19 20 21 22 23!$!24");

注:下一系列是单行命令计算相关。敬请期待。

作者:yexiaobai原文地址:https://segmentfault.com/a/1190000000504908

%s 个评论

要回复文章请先登录注册