perl一行式程序系列文章:Perl一行式


假如文件file.log内容如下:

root   x 0     0 root   /root     /bin/bash
daemon x 1     1 daemon /usr/sbin /usr/sbin/nologin
bin    x 2     2 bin    /bin      /usr/sbin/nologin
sys    x 3     3 sys    /dev      /usr/sbin/nologin
sync   x 4 65534 sync   /bin      /bin/sync

每行后加一空行

$ perl -pe '$\ = "\n"' file.log

结果:

root   x 0     0 root   /root     /bin/bashdaemon x 1     1 daemon /usr/sbin /usr/sbin/nologinbin    x 2     2 bin    /bin      /usr/sbin/nologinsys    x 3     3 sys    /dev      /usr/sbin/nologinsync   x 4 65534 sync   /bin      /bin/sync

这里出现了选项 -p 和 -e,出现了特殊变量$\,附带的,稍后还会解释另一个选项 -n。

perl的"-e"选项表示后面接perl的一行式表达式,就像sed的-e选项一样。这是一行式perl程序最常见的一个选项。perl还有一个"-E"选项,和"-e"一样都用来指定一行式表达式,但"-E"可以使用一些高版本的功能。

perl的"-p"选项表示print操作,即对每一读入的行在经过表达式操作后都默认输出,和sed的p命令是一样的。

实际上,perl中的"-p"选项等价于下面的逻辑,理解了这个逻辑,对理解sed的逻辑会很有帮助。

while(<>){... -e 指定的表达式代码在这里 ...
} continue {print or die "-p failed: $!\n";
}

Perl中的continue和其它语言的continue有点不一样,Perl中的continue表示每轮循环的主体执行完之后,执行另一段代码。也就是说,每一行内容经过"-e"指定的表达式处理后,都会被continue代码块中的print输出。

解释下-p选项的过程:while(<>)每次读取一行数据赋值给默认变量$_,然后经过-e的表达式进行处理,处理完后执行continue的print,这里print没有参数,所以表示输出默认变量$_的内容,也就是被处理后的行数据。

另一个选项 -n ,表示处理文件但默认不输出处理后的行。如果想要输出,只能自己在-e表达式中指定输出操作(print/say/printf)。逻辑为:

while (<>) {...  # -e expression here
}

也就是说,-n和-p两个选项会自动读取文件(如果都存在,则-p会覆盖-n),不需要在-e的表达式中自己写读取文件的逻辑。如果没有这两个选项,那么在-e中要自己写才能读参数文件:

$ perl -e 'while(<>){...}'

一般来说,选择使用-p还是-n的规则如下:

  • 某些行不需要输出或者需要被删除的时候,不应该使用-p,因为它默认会输出所有行

    • 换句话说,如果不需要输出所有行时,不使用-p,需要输出所有行,可以考虑使用-p
  • 不使用-p的时候,几乎都可以使用-n

最后是关于特殊变量$\表示print的输出行分隔符(awk的ORS变量),它默认为undef,所以print输出的每段数据之间都是紧连在一起的。此处示例将$\指定为换行符。

由于<>读取数据时已经将文本中每一行的\n也读取了,所以加上$\已经有两个连续的\n,于是每行后面都会多一空行。

实际上没有必要为每一读入的行都设置$\,可以将它设置在BEGIN块中:

$ perl -pe 'BEGIN{$\ = "\n"}' file.log

对于本示例"每行之后加上空行"有多种解决方式。例如:

$ perl -pe '$_ .= "\n"' file.log
$ perl -nE 'say "$_\n"' file.log
$ perl -pe 's/$/\n/' file.log
......

每行后加空行,但空行除外

$ perl -pe '$_ .= "\n" unless /^$/'

这里使用unless逻辑进行空行匹配,如果匹配空行,就不对当前行追加尾随换行符。unless测试等价于if的否定测试。

有些空行可能是包含了空白符号(空格、制表符等)的行,这些空白肉眼不可识别,但却占了字符空间,使得无法匹配^$,所以更好的匹配模式是:

$ perl -pe '$_ .= "\n" if /\S/'

\S表示任意单个非空白字符,\s表示任意单个空白字符。所以这里的逻辑是:只要行能匹配非空白字符,就追加尾随换行符。

每行后加N空行

想在每行后面加两空行、三空行、四空行、N空行该如何解决?

$ perl -pe '$_ .= "\n" x 3' file.log

Perl的字符串可以使用小写字母x表示重复N次,例如"a" x 3得到"aaa","ab" x 2得到"abab"。上面的示例表示为每行都追加3个换行符。

通过字符串重复操作,可以很轻松地输出等长的分割线:

$ perl -e 'print "-" x 30,"\n";print "hahaha\n";print "-" x 30,"\n";print "heihei\n";'
------------------------------
hahaha
------------------------------
heihei

每行前加空行

最简单的方式是使用s替换操作。

$ perl -pe 's/^/\n/' file.log

移除所有空白行

$ perl -ne 'print unless /^$/' file.log

此处使用了"-n"选项,表示禁止默认的输出。print和匹配操作的对象都使用默认变量$_。等价于:

整个逻辑是:只要匹配了空行/^$/,就不输出。

这也有好几种方式可以实现,例如:

$ perl -ne 'print if /\S/' file.log

比较独特的一种实现方式是使用length函数:

$ perl -lne 'print if length' file.log

这里涉及选项"-l"和函数length(),且print和length都没有指定操作对象,所以使用默认变量$_,等价于:

$ perl -lne 'print $_ if length $_' file.log

length函数可以获取字符串的字符个数,注意是字符数不是字节数。

-l选项在结合-n或-p使用的时,会自动对读入的行移除尾随换行符,然后在输出的时候自动追加尾随输出分隔符(如换行符,如何追加分隔符请参看Perl一行式参考手册)。

这里的逻辑是:如果是空行,那么在被-l移除换行符后length返回0,也就是布尔假,所以只有不是空行的行才会被输出。

压缩连续空行:按段落读取

先准备一段测试数据paragraph.log:

first paragraph:first line in 1st paragraphsecond line in 1st paragraphthird line in 1st paragraphsecond paragraph:first line in 2nd paragraphsecond line in 2nd paragraphthird line in 2nd paragraphthird paragraph:first line in 3rd paragraphsecond line in 3rd paragraphthird line in 3rd paragraph

sed/awk中想要压缩连续空行,总要多读入几行进行连续空行的判断。例如:

$ sed -nr '$!N;/^\n$/!P;D' paragraph.log

但在perl一行式中,这会变得无比的简单:

$ perl -00pe '' paragraph.log

这里两个关注点:-00-e ''

-e ''的表达式部分为空,表示什么也不做。什么也不做的时候,也可以写成-e0

$ perl -00pe0 paragraph.log

-0OCTNUM表示设置输入行分隔符$/

如果省略8进制值OCTNUM,则-0表示设置$/为undef,即$/ = undef,也就是一次性从文件头读到文件尾当作一行赋值给$_

这里指定了8进制的值为0,对应于ASCII的空字符串,即等价于$/ = "",它表示按段落读取(slurp读取模式),并压缩连续的空行为单个空行。

什么是段落?中间隔了至少一空行的是上下两个段落,段落意味着可能包含了连续的多行。但是如果隔了连续的空行呢?设置$/ = ""会按段落读取,并压缩连续的空行为单空行,然后作为上面的段落的一部分。设置$/ = "\n\n"也表示按段落读取,但它不会压缩连续的空行。

如何知道是否是按段落读取?可用下面的示例进行测试:

$ perl -ne 'BEGIN{$/ = "";}print $_."xxxxx" if /2nd/' paragraph.log

会发现追加的几个字符"xxxxx"是单独附加在第二段落的尾部的,而不是能匹配"2nd"的每一行上。

压缩/扩展所有连续空行为N空行

在上面一节压缩连续空行的基础上,实现这个目的已经非常容易了:

$ perl -00pe '$_ .= "\n" x 3' paragraph.log

这表示将每个段落之间规范为4个连续的空行进行分隔。之所以是4空行而不是3,是因为压缩成单空行后,又追加了3空行。

压缩/扩展单词间的空格数量

要实现这样的功能,这个对于sed来说也非常的容易。这里给几个简单示例。

1.每行单词间的空给双倍化:每个空白都扩成2空格

$ perl -lpe 's/ /  /g' file.log

2.移除每行单词间的所有空白

$ perl -lpe 's/ //g' file.log

3.每行单词间连续空白压缩为单空格

$ perl -lpe 's/\s+/ /g' file.log

4.所有字符间插入一个空格

$ perl -lpe 's// /g' file.log

注意,上面插入空格时,也会在行首和行尾插入空格符号。

直接修改文件

perl的"-i"选项可以用来原地修改、拷贝副本。用法和sed的"-i"一致。

例如:

$ perl -i".bak" -lpe 's/$/\n/g' file.log$ cat file.log
root   x 0     0 root   /root     /bin/bashdaemon x 1     1 daemon /usr/sbin /usr/sbin/nologinbin    x 2     2 bin    /bin      /usr/sbin/nologinsys    x 3     3 sys    /dev      /usr/sbin/nologinsync   x 4 65534 sync   /bin      /bin/sync$ cat file.log.bak
root   x 0     0 root   /root     /bin/bash
daemon x 1     1 daemon /usr/sbin /usr/sbin/nologin
bin    x 2     2 bin    /bin      /usr/sbin/nologin
sys    x 3     3 sys    /dev      /usr/sbin/nologin
sync   x 4 65534 sync   /bin      /bin/sync

转载于:https://www.cnblogs.com/f-ck-need-u/p/10219742.html

Perl一行式:处理空白符号相关推荐

  1. Perl一行式:文本编解码、替换

    perl一行式程序系列文章:Perl一行式 文本大小写转换 全部字符转换成大写或小写,有几种方式: # 转大写 $ perl -nle 'print uc' file.log $ perl -ple ...

  2. perl 一行命令 2021-09-02

    生物信息入门常用 perl 'one-liner'–by CJ chen convert -delay 10 -resample 10% ls|perl -lane '/CJ\d{4}\d{4}(\d ...

  3. 处理tcga突变数据一点思考

    TCGA突变数据 写在前面 泛癌mc3作图 学到的额外知识点 使用TCGAbiolinks下载数据 TCGA关于maf的注释 代码文件夹命名最好还是以英文命名,中文命名经常会出现错误 GTF文件有的以 ...

  4. Perl正则表达式超详细教程

    前言 想必学习perl的人,对基础正则表达式都已经熟悉,所以学习perl正则会很轻松.这里我不打算解释基础正则的内容,而是直接介绍基础正则中不具备的但perl支持的功能.关于基础正则表达式的内容,可参 ...

  5. python perl r_PHP Python Ruby Perl

    PHP的魅力所在提起老牌经典脚本语言PHP,我们不禁会联想到它的一个令人印象深刻的特点,即上手快,你无需对这个语言进行深入广泛的了解就可以使用它开始编程.在我们知道的语言中,没有几个语言能把这种特点体 ...

  6. php与python缺点_php,python,ruby,perl的优缺点?

    提问者采纳 2012-02-25 08:41 perl基本已经被淘汰,在各方面几乎已经没有优势,虽然说还正在开发perl6啊什么的,不过基本上大势已去.虽然在部分场合还有应用,不过大部分都只是因为历史 ...

  7. Perl,PHP,Python,Ruby概要及各自特点

    http://run-wang.iteye.com/blog/1290061 程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言.从这个观点看,Perl,Python,Ruby是动态语言,C ...

  8. 一文了解Perl语言

    我在公众号发过很多编程语言的学习笔记,但是一直没有发Perl语言的编程教程.我大学的时候,学过一段时间的Perl语言,所以和Perl也有点缘分.这次去北京参加培训时发现他们教的Perl,所以接着机会发 ...

  9. 正则表达式grep、egrep--already

    第一式  grep是什么   #man grep grep(global search regular expression(RE)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打 ...

最新文章

  1. You're AllSet! 以多重集函数角度重新检视超图GNN
  2. Enable-Migrations出错
  3. Sass mixin与extends、%placeholder、function
  4. string修饰的梦修改吗_知识点!!!NSString用copy和strong修饰的区别
  5. python闭包函数的必要条件_Python 函数 functions、闭包 closure
  6. python地址簿3.7版本_用python编写地址簿程序的问题
  7. Spring Boot 项目优化和Jvm调优 (楼主亲测,真实有效)
  8. python3 主函数_Python3---常见函数---if __name__ == __main__
  9. JSPstudy恢复80端口
  10. C语言实现扩展欧几里得算法
  11. 高颜值的第三方网易云播放器YesPlayMusic
  12. 小学计算机无生试讲教案,小学英语无生试讲
  13. Linux内核和传统Unix内核的比较
  14. 听劝!不要啥都不懂就学PMP!这100个考试关键点,带你直击考试现场
  15. NMI 代码实现步骤
  16. 《星际探索》首席数码绘景师为你解析Blender场景制作
  17. java定时器整点报时_单片机 整点报时 定时小闹钟程序
  18. 前端、后端、测试,究竟应该如何抉择?
  19. Facebook SDK for iOS 2.4 iOS 6 上运行崩溃
  20. uniapp设置导航栏、沉浸式导航栏以及获取屏幕尺寸

热门文章

  1. mysql客户端报错1366_mysql一些异常
  2. 一步一步学Linq to sql(八):继承与关系
  3. 淘宝开放平台正式环境获取数据(一)
  4. 又双叒叕是一个动态简历
  5. 设计模式之-简单工厂模式
  6. 从 JavaScript 到 TypeScript
  7. Codeforces Round #345 (Div. 1) D. Zip-line 上升子序列 离线 离散化 线段树
  8. 从软件质量看如何写代码(1)
  9. 你不了解PHP的10件事情!
  10. 腾讯暑期日常实习前端面试