注:该文写作来自于 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");
注:下一系列是单行命令计算相关。敬请期待。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。