perl one-liners explained,是继《Famous Awk One-Liners Explained》和《Famous Sed One-Liners Explained》,后Peteris Krumin推出的又一个系列文章,并已经出书了。本blog会陆续对其进行翻译成中文,以便大家学习。本篇是第五部分——文本转化和替换
原文地址:http://www.catonmat.net/download/perl1line.txt
原书blog地址:http://www.catonmat.net/blog/perl-book/
本翻译项目地址:https://github.com/bollwarm/perlonelinecn
文本转化和替换
63.ROT13化字串
1 2 |
'y/A-Za-z/N-ZA-Mn-za-m/' |
本行代码使用y操作符(或者页脚tr操作符)做ROT13转化。y和tr操作做会对搜索列表的字符以替换列表对应位置的字符逐字替换。
本行代码A-Aa-z生成如下的字符列表:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
而N-ZA-Mn-za-m 生成的列表为:
NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm
如果你观察的比较仔细的话,就可以看出来第二行列表实际上和第一个列表偏移了13个字符。于是用y操作符把第一个列表所有字符用第二列表替换,你正好就执行了ROT13操作。
如果你要对整个文件做ROT13:
1 2 |
perl -lpe 'y/A-Za-z/N-ZA-Mn-za-m/' file |
-p参数会把文件的每行都放到$_变量中,y做ROT13操作,在用-p输出$_out.-l参数附加一个换行符。 注意:ROT13两次会得到同样的字符。例如,ROT14(ROT13(string))==string。
64.Base64加密
1 2 |
perl -MMIME::Base64 -e 'print encode_base64("string")' |
本行代码使用MIME::Base64模块(Perl核心自带,无需额外安装)。这个模块的encode_base64函数接受字串为参数,对其做Base64加密。 如果对整个文件做加密,使用下面代码:
1 2 |
perl -MMIME::Base64 -0777 -ne 'print encode_base64($_)' file |
此处-0777参数和-n用在一起导致Perl加载整个文件到$_变量。接着对其中base64加密,就像上面的字串的例子一样的。 如果我们不加载整个文件,而是通过逐行加密的话结果会混乱。
65.base64解码
1 2 |
perl -MMIME::Base64 -le 'print decode_base64("base64string")' |
MIME::Base64模块也有解码函数decode_base64.decode_base64函数接收base64加密的字串,对其进行解码。
对这个文件解码也可以很简单:
1 2 |
perl -MMIME::Base64 -ne 'print decode_base64($_)' file |
此处不需要加载整个文件到$_,因为base64加密的文件每一行都恰好为76个字符,很好解码。
66.对字串URL转码
1 2 |
perl -MURI::Escape -le 'print uri_escape($string)' |
你需要安装另外URI::Escape模块,这个模块输出两个函数uri_escape 和uri_unescape,第一做url转码,另一个做URL解码。
67.对字串URL解码
1 2 |
perl -MURI::Escape -le 'print uri_unescape($string)' |
本行代码使用uri_unescape函数做URL解码。
68.对字串做HTML转码
1 2 |
perl -MHTML::Entities -le 'print encode_entities($string)' |
本行代码使用HTML::Entities 模块的encode_entities函数。这个函数用来转码HTML实体。例如,把 < 和 >转化为<和>
69.对字串做HTML解码
1 2 |
perl -MHTML::Entities -le 'print decode_entities($string)' |
本行代码使用HTML::Entities 模块的deencode_entities函数。
70.所有文本大写
1 2 |
perl -nle 'print uc' |
本行代码使用uc函数,它默认对$_变量进行操作,并且返回其大写形式。
另外一种方法是用-p命令行选项使其自动打印$_变量并且对其就地处理:
1 2 |
perl -ple '$_=uc' |
也可通过使用\U转义序列的方法达到同样的功能:
1 2 |
perl -nle 'print "\U$_"' |
这会让其后所有的字符(或者直到出现\E为止)都大写。
71.所有文本小写
1 2 |
perl -nle 'print lc' |
本行代码和前一例完全相似,不过此处使用的lc函数爸$_的内容转化为小写。 或者,使用转义序列\L做字符改写:
1 2 |
perl -nle 'print "\L$_"' |
此处\L会让其后所有的字符(或者直到出现\E为止)都小写。
72.对每行的首字母大写
1 2 |
perl -nle 'print ucfirst lc' |
本行代码使用lc函数使输入的转化为小写,并利用ucfirst函数似的第一个字字符大写。
也能用转义码文本转换的方法实现同样的功能:
1 2 |
perl -nle 'print "\u\L$_"' |
第一个\L使整行都小写,\u使得第一个字符大写。
73.大小写转化
1 2 |
perl -ple 'y/A-Za-z/a-zA-Z/' |
本行代码把大写字母A-Z转化为小写a-z,而把小写字母大写,从而实现了大小写转化。
74.每行进行驼峰大小写转化
1 2 |
perl -ple 's/(\w+)/\u$1/g' |
这是一个差劲的驼峰表示法行代码。它会把每个单词的首字母都大写。对诸如“fried’s car”会转化有误,会把它转化为“ Friend’S Car”。
一个改进是:
1 2 |
s/(?<!['])(\w+)/\u\1/g |
它会检查是否一个单词前的字符是不是单引号“’”。但是在某些更特殊的情况下它可能仍然会失败。
75.去除每行前面的空白(空格,tab等)
1 2 |
perl -ple 's/^[ \t]+//' |
本行代码删除了所有的每行前面的所有空格。他使用替换操作符s。对一个模式s/REGEX/REPLACE/会把匹配的REGEX用REPLACE字串代替。在本例中REGEX是^[ \t]+,意思是在字符串的开始匹配一个或者更多个空格或者tab;REPLACE为空,意思是把匹配部分替换为空字串(删除)。
正则类[ \t]实际上可以用\s+来替换,\s+匹配任何的空格(包括tabs和空格):
1 2 |
perl -ple 's/^\s+//' |
76.删除每行的每行末的空白
1 2 |
perl -ple 's/[ \t]+$//' |
本行代码删除了每行末所有空白字符。
77.删除每行开始和结束的空白
1 2 |
perl -ple 's/^[ \t]+|[ \t]+$//g' |
本行代码结合了前面两例。注意到,它给操作符指定了全局的/g标记。这是必须的,由于我们期望删掉开始和结束的空白。如果我们不指定,他将只能删除开始的(假设存在的话),而不会删除最后的。
77.转化Unix换行符为DOS/Windows换行符
1 2 |
perl -pe 's|\n|\r\n|' |
本行代码替换Unix换行符\n LF为windows换行符\r\n CRLF。记住s操作符可以使用任何字符作为分隔符。本行代码用竖线作为分隔符,以增加代码的可读性。
78.转化DOS/Windows换行符为UNIX换行符。
1 2 |
perl -pe 's|\r\n|\n|' |
本行代码做了前一例的逆操作。操作window 换行发CRLF,并把它转化为换行符LF。
79.转化Unix换行符为Mac换行符。
1 2 |
perl -pe 's|\n|\r|' |
苹果使用\r CR作为换行符。本行代码转化Unix的LF为苹果的CR。
80.替换行中foo为bar(查找替换)
1 2 |
perl -pe 's/foo/bar/' |
本行代码使用s/REGEX/REPLACE/对每行中foo的替换为bar
替换行中所有foo为bar,则需要增加/g标记:
1 2 |
perl -pe 's/foo/bar/g' |
81.替换匹配“baz”的行中的foo为bar
1 2 |
perl -pe '/baz/ && s/foo/bar/' |
本行代码等价于:
1 2 3 4 5 6 |
while (defined($line = <>)) { if ($line =~ /baz/) { $line =~ s/foo/bar/ } } |
他先检查每行是否匹配“baz”,如果匹配,则替换行中foo为bar。
82.逆序输出段落
1 2 |
perl -00 -e 'print reverse <>' file |
本行代码使用了-00参数,这在例7讨论过,用来开启大段落模式,意味着Perl将通过段落的方式读取文本,而不是默认的按行的方式。接着使用<>操作符使得Perl用指定的文件或者标准输入获得输入。本处我们指定file作为参数,所以Perl读取file的文本段落(由于-00)。当Perl读完文件,它将所有段落作为一个列表返回,并且调用reverse函数颠倒段列表的顺序。最后打印出反序的段落列表。
83.逆序输出所有行
1 2 |
perl -lne 'print scalar reverse $_' |
本行代码在标量上下文下reverse操作。在上一例中,对整个列表在在列表上下文中执行reverse,结果是对列表元素顺序进行反序。对标量变量,比如包含整行的$你要实现同样的功能必须在标量上下文进行reverse操作。否则,它执行的将会对一个元素的列表rreverse,得到结果还会是他自己!作为操作后,打印出反序的行。你可以去掉代码中$,执行结果一样的。因为reverse默认的变量就是$_。换句话说,行代码可以写为:
1 2 |
perl -lne 'print scalar reverse' |
或者你可以用-p替换-n,修改$_变量,使其值为倒序:
1 2 |
perl -lpe '$_ = reverse $_' |
也可以简写为:
1 2 |
perl -lpe '$_ = reverse' |
要说明的是在Perl的操作符如果没有指定参数的话,大多数情况下默认都是对$_操作。
84.以逆序方式打印列
1 2 |
perl -alne 'print "@{[reverse @F]}"' |
本行代码对文件中的列逆序转化。-a命令行参数用空格为分隔符切割每一行为列并存在@F数组中。接着对其逆序并且打印。
本行代码在以有过类似的例子,@{[…]}结果,为了解释其作用,我们假设在其中插入了双引号,给予下面的输入文件:
one two three four five six seven eight
其输出为:
four three two one eight seven six five
如果输入的行的各列直接不是空格而是其他的分隔符,则我们必须用-F命令行设置为特殊的字符,如果给输入文件为:
one2️⃣three:four five6️⃣seven:eight
这我们增加-F:参数,给行代码:
1 2 |
perl -F: -alne 'print "@{[reverse @F]}"' |
它的输出为:
four three two one eight seven six five
注意到,在输出的时候没有带:字符,为了使其带上,我们需要对本行修改,设置$”变量为“:”,如下:
1 2 |
perl -F: -alne '$" = ":"; print "@{[reverse @F]}"' |
他会输出我们所期望的结果:
four3️⃣two:one eight7️⃣six:five
变量$”用于改变在双引号环境下对数组进行变量内插打印时元素间默认的分割字符(空格)。
好东东,学习,学习