注:该文写作来自于 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,querytime,$key) values ( \'$log[0]\',\'$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,\'$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,\'$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");
注:下一系列是单行命令计算相关。敬请期待。