9.5 KiB
有选择的打印或者删除行
85.打印文件的首行(模仿head -1)
perl -ne 'print; exit'
本行代码迄今为止最简单一个。此处由于使用-n参数Perl读了第一行到$_,接着调用print语句输出 $_变量的内容。接着推出。就这样,第一行就被打印出来了,而这恰好就是我们需要的。
86.打印文件开始的10行(模仿head -10)
perl -ne 'print if $. <= 10'
本行代码是使用了.特殊变量。这个变量带包“当前行序号”。每次Perl读下一行的时候,.的值为自动加一。因此本行代码非常好理解:当行序号等于或者小于10的时候,打印出行内容。
本行代码也可以用不带if语句的方法:
perl -ne '$. <= 10 && print'
此处,只有当$.<=10布尔表达式为true时执行打印语句,而只有行号小于或者等于10时候表达式为真。
87.打印最后一行(模仿tail -1)
perl -ne '$last = $_; END { print $last }'
打印最后一行的代码需要一点技巧,因为你一直需要把前一行保存在内存里。本行代码总我们一直把当前行保存到$last变量。当Perl代码结束时候,总会执行END块的。现在当读完最后一行,执行END块,退出的时候,我们打印出$last变量,这就是最后一行的内容。 另外一种同样同能代码是,
perl -ne 'print if eof'
本行代码使用eof函数,这个函数在下一次读到文件的末尾时候返回1。由于读到文件最后一行的时候,下一行读(文件末尾)返回eof为真,所以本代码作出了我们期望所做的事情。
88.打印文件的最后10行(模拟tail -10)
perl -ne 'push @a, $_; @a = @a[@a-10..$#a]; END { print @a }'
这个有点复杂。此处我们把每一行都put到数组@a中,然后用他的数组切片代替他。我们做 @a = @a[@a-10..$#a],这表示用@a的最后10个元素取代他自己。@a-10在标量上下文被估值,他返回值为数组元素个数减10。#$a是@a数组的最后一个下标。@a[@a-10..#$a]取得了数组的最后10个元素的下标,所以@a保存了最后10个元素。
举例子假设数组@a保存("line1", "line2", "line3", "line4")。我们想要打印文件最后4行。当我们读到滴5行时候,数组变成了("line1", "line2", "line3", "line4", "line5")。这时,由于@a在标量环境下估值为5,@a-4值为1。#$a值为4。数组切片@a[@a-4..$#a]则为@a[1..4],这去掉了数组中的第一个元素。当作为替换后@a就变成了("line2", "line3", "line4", "line5")。
89.仅打印匹配模式的行。
perl -ne '/regex/ && print'
此处/regex/是$_ =~ /regex/的缩写。由于-n操作符会把每一行都放到$_变量中,所有匹配模式的行/regex/会返回true,就会打印出行内容。
90.仅打印模式不匹配的行。
perl -ne '!/regex/ && print'
本行和尚一行基本上一样,但是模式表达被取反了。于是会打印所有不匹配的行。
91.打印匹配行之前的一行。
perl -ne '/regex/ && $last && print $last; $last = $_'
本行代码中我们把每一行的内容保存到$last变量中。当行匹配模式的时候,$last中是其上一行的内容,于是打印$last,接着把当前行的内容复赋值给$last变量。
92.打印模式匹配行之后的一行。
perl -ne 'if ($p) { print; $p = 0 } $p++ if /regex/'
此处如果行匹配模式的话我们设置变量$p的值。用它指示下一行将会被打印。当下一行被读到,$p被设置,于是这行被打印,并且$p被又被设置为0,重置其状态。
93.打印任意顺序匹配AAA和BBB的行。
perl -ne '/AAA/ && /BBB/ && print'
本行代码基本上和此前例86一样,只不过这儿测试的模式变成了两个,如果一个行匹配了两个模式,他就会被打印出来。
94.打印不匹配AAA和BBB模式的行。
perl -ne '!/AAA/ && !/BBB/ && print'
本行代码基本上和此前例87一样,此处测试行是否不匹配任意顺序两个模式。如果不匹配/AAA/ 并且不匹配/BBB/,我们打印出这行。
95.打印匹配模式AAA接着模式BBB,再接着模式CCC的行。
perl -ne '/AAA.*BBB.*CCC/ && print'
此处简单的将三个模式AAA,BBB,CCC用“.*”连了起来,表示匹配这所有的或者不匹配。如果AAA跟着BBB又跟着CCC模式,这行就会被打印。他也会匹配AAABBBCCC这样的。
96.打印所有80字符或者大于80字符的行
perl -ne 'print if length >= 80'
本行代码打印所有大于或者等于80字符的行。Perl中你时常可以省略掉函数调用时候的括弧()。此处我们省略了长度函数的括弧。实际上,length,length() 和length($_)都是一样的。
97.打印小于80字符的行。
perl -ne 'print if length < 80'
这和前一行代码相反。检测行长度是否小于80字符。
98.仅带打印13行
perl -ne '$. == 13 && print && exit'
和此前例13介绍的一样,.变量表示当前行数。所以,如果.等于13,我们就打印了13行,并退出。
99.打印除27行外的所有行。
perl -ne '$. != 27 && print'
和上一行代码类似,我们检测当前行是否为27行,如果不是我们打印它,否则跳过。 另一种实现同样功能的方式是颠倒print和$.!=27,使用if语句。
perl -ne 'print if $. != 27'
100.仅打印13,19和67行。
perl -ne 'print if $. == 13 || $. == 19 || $. == 67'
如果你是用Perl 5.10或者更新版本你可以使用~~~智能匹配符,
perl -ne 'print if int($.) ~~ (13, 19, 67)'
智能匹配符“~~”仅在Perl 5.10才推出。你可以用它做所有类型的智能模式匹配。例如,检查是否两个数组是一样的;是否一个数组包含一个元素,以及其他很多用法(见perldoc perlsyn)。在本行代码中我们使用 int(.)~~(13,19,67) 用来检测是否数值.在列表(13,19,67)中。这基本上是对代码 grep {_==int(.)} (13,19,67)缩写。如果检测成功,行就会被打印。
101.打印匹配两个模式之间的所有行(包括匹配模式的行)
perl -ne 'print if /regex1/../regex2/'
本行代码使用触发操作符,当某行匹配regex1他变为ture,当其后另一行匹配了regex2时候变为false。因此这个行代码就会打印出匹配了两个模式之间的所有行。
102.打印17到30之间所有行
perl -ne 'print if $. >= 17 && $. <= 30'
本行代码非常容易理解。$.变量表示当前行号,于是它检测是否当前行号大于等于17并且小于等于30。 另一种写法是,
perl -ne 'print if int($.) ~~ (17..30)'
这行代码使用Perl5.10(或者更新版本)的智能匹配操作符~~。这主要是说,当前行号在列表(17, 18, 19, ..., 30)。如果是,智能模式符匹配成功,行就会被打印。 在老Perl版本你可以用下面的代码代替,
perl -ne 'print if grep { $_ == $. } 17..30'
这主要是用grep过程探测,是否当前行号在列表(17, 18, 19, ..., 30)。如果是,返回列表中的一个元素,而有一个元素的列表表示为真,所以行就会被打印。否则的话返回一个空列表,代表为false,就不会得到打印。
103.打印最长的行。
perl -ne '$l = $_ if length($_) > length($l); END { print $l }'
本行代码保存目前看得见最长的行到$l变量中。一旦当前行$_超过了迄今最长的行,就替换它。最后退出之前,在END块执行打印出最长的行$l。
104.打印最短的行。
perl -ne '$s = $_ if $. == 1; $s = $_ if length($_) < length($s); END { print $s }'
本行代码和上一例正好相反。但是我们要找到最短的并且由于$s在首行没有定义,我们必须显式的指定其为第一行,不然后面的小于判断都会失败,得不到想要的结果。
105.打印包含数字的所有行
perl -ne 'print if /\d/'
本行代码使用正则表达式\d,这表示匹配一个数字,检查是否包含,如果包含,检测成功,打印出行。
106.发现仅仅包含一个数字的行。
perl -ne 'print if /^\d+$/'
本行代码和一例相似,不过匹配的不是一行中有个数字,而是锚定行的开始和结束。正则表达式^\d+$表示匹配在行首和行尾之间的一个或者多个数字。
107.打印仅仅包含字母的行。
perl -ne 'print if /^[[:alpha:]]+$/'
本行代码检测是否行中只含有字母,如果是打印出行。此处:alpha:表示匹配所有的字母。你也可以写为[a-zA-Z]。
108.隔行打印。
perl -ne 'print if $. % 2'
本行代码打印第一,三,五,七等等行。因为$. % 2当当然行号为奇数时候返回真,当前行为偶数时候返回false。
109.从第二行开始隔行打印
perl -ne 'print if $. % 2 == 0'
本行代码和上一例非常相似,但是打印的不是,1,3,5,7,而是2,4,6,8等偶数行。这由于当行号为偶数时候$. % 2 == 0为真。
110.打印所有重复的行。
perl -ne 'print if ++$a{$_} == 2'
本行代码用哈希%a保存了目前为止的所有行,并且计算这些行出现的次数。如果某行出现2次,他就会被打印出,因为此时++$a{$_} == 2为真。如果此行计数多余两次,他不会做任何操作,因为此行已经超过2行,打印检测为false。
111.不重复的打印所有行
perl -ne 'print unless $a{$_}++'
此处,只有行的哈希值$a{$_}为0时候才会打印。每一次Perl读进一行,都会将这个值增加1,所以这使得只有之前都没有出现过的行被打印。