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
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞