Perl one line command – 空白与数字
Perl one line command - 空白与数字
一. 空白处理 本节说明 Perl 命令行对空白(空行, 制表符)的一些常见处理, 同样以一些示例来说明.
1. 多倍行距 使用特殊符 $\ 来完成多倍行距, $\ 特殊符相当于在每个 input 行后面额外增加了指定的 $\ 变量, 如果要将行距扩充两倍, 可以如下操作:
perl -pe '$\ = "\n"' file
在每行后面再增加一个换行符, 转换为如下代码:
while(<>) {
$\ = "\n";
print $_ or die "-p failed: $!\n";
}
也可以使用 BEGIN 只对 $\ 做一次赋值:
perl -pe 'BEGIN{ $\ = "\n" }' file
上面的示例等效于:
perl -pe '$_ .= "\n"' file
perl -pe 's/$/\n/' file # 每行结尾改为换行符
perl -nE 'say' file # Perl 5.10 版的新特性, -E 为开启 Perl 5.10 版特性, say 类似 print, 但增加了换行操作.
如果是多倍行距, 可以使用 “\n”xm(换行符重复m次), 如下3倍行距:
perl -pe '$\ = "\n"x3' file
2. 空行处理
perl -pe '$_ .= "\n" unless /^$/' file
unless 等同 if not, ^$表示匹配空行(^表示开始, $表示结束), 如果空行中存在制表符的话, ^$ 并不会匹配上, 这个示例等同下面:
perl -pe 'print if length' file
如果不为空行(空行length应该为0)则打印, 如果存在制表符的行, print 还是会打印出来, 可以使用下面的代码:
perl -pe 'print if /\S/' file
\S正则匹配非空白字符(空格, 制表符, 新行, 回车等), 索引上述的两个示例并不会过滤制表符类的空行.也可以在每行之前增加一个空行:
perl -pe 's/^/\n/' file
我们将 -p 参数改为 -n 参数即可移除所有的空行, 因为 -p 本身就会打印出当前行内容:
perl -ne '$_ .= "\n" unless /^$/' file
perl -ne 'print if /\S/' file
3. 多个空白行改为一个空白行或指定行距 如下所示:
perl -00 -pe '' file
perl -00pe0 file
使用 perldoc perlrun 可以搜索到 -00, -0777所表示的意思, 00表示按照段落读取(slurp files in paragraph mode), 替代了原先的按行读取, 0777表示整个文本读取, -00指定了按照段落读取内容, 再输出来, 最后就实现了多个空行改为了一个空行. 这里的 -e ‘’ 和 e0 表示什么都不做. 同样的, 使用下面的代码可以将一个行距扩充到多个:
perl -00 -pe '$_ .= "\n"x3' file # 每段落增加了3个换行符
4. 单词之间的距离
perl -pe 's/ / /g' file
将一个空格扩充到2个空格. 也可以移除单词之间的空格:
perl -pe 's/ +//g' file
+(前面有个空格) 表示匹配一个或多个空格.如果有制表符,换行符等, 需要用 \s+ 来匹配:
perl -pe 's/\s+//g' file
也可以在每个字符之间插入一个空格:
perl -lpe 's// /g' file
二. 数字处理
本节说明 Perl 命令行对数字的处理.
1. 行号 使用 $. 特殊符表示行号, $_ 表示当前行内容:
perl -pe '$_ = "$. $_"' file
perl -ne 'print "$. $_"' file
排除空行的行号:
perl -pe '$_ = ++$x." $_" if /./' file #打印空行, 但不显示行号
perl -pe '$_ = ++$x." $_" if /\S/' file #打印空行, 但不显示行号
perl -ne 'print ++$x." $_" if /./' file #不打印空行
perl -ne 'print ++$x." $_" if /\S/'file #不打印空行
记录所有行号, 但是不打印空行:
perl -pe '$_ = "$. $_" if /./' file
perl -pe '$_ = "$. $_" if /\S/' file
只生成匹配规则的行号, 但是也打印没有匹配的行:
# perl -pe '$_ = ++$x." $_" if /there/' file
1 how there are
list file
2 there are
只生成匹配规则的行号, 但是不打印没有匹配的行:
# perl -ne 'print ++$x." $_" if /there/' file
1 how there are
2 there are
生成所有行的行号, 但是只打印匹配规则的行:
# perl -pe '$_ = "$. $_" if /there/' file
1 how there are
list file
3 there are
2. 输出格式
# perl -ne 'printf "%-5d %s", $., $_' file
1 how there are
2 list file
3 there are
# perl -ne 'printf "%5d %s", $., $_' file
1 how there are
2 list file
3 there are
# perl -ne 'printf "%05d %s", $., $_' file
00001 how there are
00002 list file
00003 there are
使用 printf 函数格式化输出.
3. 打印文本的总行数(类似 wc -l)
# perl -lne 'END{ print $. }' file
3
下面示例等同上面的代码:
perl -le 'print $n = () = <>' file
perl -le 'print $n = (() = <>)' file
perl -le 'print scalar(@fo = <>)' file
这里没有使用 -p 或 -n, <> 表示 file 的文件句柄(所有内容), () = <> 表示将内容放到列表环境中(每个元素为一行内容), 再将 () = <> 复制给 $n, 这时候为标量上下文, $n 的值为列表元素的数量, 所以最后打印出文本的行数. scalar(@fo = <>) 同理.下面的则稍有点不同:
perl -nle ' }{ print $.' file
这个表达式看起来很奇怪, 这里用到了 -n (等同在代码周围增加了while(<>){ }) 参数, 上面的代码等同以下:
while(<>) {
} {
print $.
}
所以也打印出了最后一行的行号.
4. 统计非空行
perl -le 'print scalar(grep { /./ } <>)' file
perl -le 'print ~~(grep { /./ } <>)' file
perl -le 'print ~~grep { /./ } <>' file
上述三条命令等效, ~~ 即表示标量环境,
5. 统计空行
perl -lne '$x++ if /^$/; END{print $x+0}' file
$x+0 避免未匹配到而引起的未初始化错误, 如果要忽略制表符等, 正则里面应该是 \S. 也可以使用 grep 打印空行数:
perl -le 'print scalar(grep {/^$/}<>)' file
perl -le 'print ~~grep{/^$/}<>' file
6. 统计匹配规则的行数(grep -c)
perl -lne '$x++ if /there/; END{print $x+0}' file
7. 单词计数 文本所有单词计数:
# perl -pe 's/(\w+)/++$i.".$1"/ge' file
1.how 2.there 3.are
4.list 5.file
6.there 7.are
s///中的e选项可以使得替换之前先执行代码, (\w)为匹配并捕获单词, 捕获后放到 $1 变量中, $i 则在每次匹配之前自增 1.下面为计数每行的单词:
# perl -pe '$i = 0; s/(\w+)/++$i.".$1"/ge' file
1.how 2.there 3.are
1.list 2.file
1.there 2.are
每次循环初始化 $i 的值即可. 下面为替换每个单词为其计数的值:
# perl -pe 's/(\w+)/++$i/ge' file
1 2 3
4 5
6 7
文章参考: PERL ONE-LINERS Copyrught @ 2014 by Peteris Krumins ISBN-10: 1-59327-520-X