[连载]Perl 命令行一句话代码,翻译+整理

There's more than one way to do it!
https://metacpan.org http://perlmonks.org
回复
头像
523066680
Administrator
Administrator
帖子: 573
注册时间: 2016年07月19日 12:14
联系:

[连载]Perl 命令行一句话代码,翻译+整理

帖子 523066680 »

编辑/整理:523066680@163.com

序:内容取自 《Perl One-Liners》,注意该教程中示例的 ' 符号(单引号)在windows 中应改为双引号,否则不会奏效。我在翻译和摘录的代码中也会改用双引号

备注:
  • 1. 不做全文翻译,尽量简明
    2. 假设看官已经有正则表达式基础
    3. 环境:Win7, Strawberry Perl 5.24 Portable Edition
Chapter 1 - Perl ONE-LINERS
  • 第一个示例,全局将文件中的 you 替换为 me:
    • perl -pi -e "s/you/me/g" file

      /g 表示全局替换
      -e 参数允许执行 Perl 代码
      -p 参数确保处理文本的每一行并且将处理后的结果打印出来
      -i 参数将修改的结果应用到文件中(所以看不到 -p 打印的内容了)
      -i[extension] edit <> files in place (makes backup if extension supplied)

      注意,实际测试 -i 参数必须提供扩展名以备份文件,否则提示:Can't do inplace edit without backup.

      perl -pi.bak -e "s/you/me/g" file
    处理多个文件:
    • perl -pi.bak -e "s/you/me/g" file1 file2 file3
    仅处理含有"we"的行:
    • perl -pi.bak -e "s/you/me/g if /we/" file
    打印文件中重复出现的行:
    • perl -ne "print if $a{$_}++" file

      $_ 表示当前遍历的行的内容
      -n 表示遍历所有行(类似 -p 但不负责打印结果)

      执行后将自动建立字典 %a,当 $_ 对应的值第一次出现的时候,$a{$_} 还是 undef(同0),+1在下次生效。再次出现时为1,打印输出,以此类推。
    添加并打印行号:
    • perl -ne "print \"$. $_\"" file

      在 Perl 中,$. 是一个特殊变量,表示当前行数。这个例子也可以改用 -p

      perl -pe "$_ = \"$. $_\"" file
    带行号,但仅显示重复行
    • perl -ne "print \"$. $_\" if $a{$_}++" f.txt
    借用 List::Util 模块统计每行中出现的数字的和
    • perl -MList::Util=sum -alne 'print sum @F' f.txt

      说明:
      -MList::Util 导入 List::Util 模块
      =sum 表示导入 List::Util 的 sum 函数
      -a 参数,自动按空格划分行的内容并保存到 @F,使单词、数字独立出来
      注 -F/pattern/ 参数可指定其他划分规则
      -l 参数确保每一次输出都换行,省了手动 "\n"
    让时间回退到 1299 天前:
    • perl -MPOSIX -le "@t = localtime; $t[3] -= 1299; print scalar localtime mktime @t"

      实际时间:
      Wed Apr 26 19:31:22 2017
      输出:
      Sat Oct 5 19:31:22 2013

      这个过程实际就是 用 @t 获取 localtime 的返回结果(数组环境),将日期减1299(在数组成员中会变成负数),再使用 mktime 将其封装,返回给 localtime,再用标量环境打印 localtime 的返回值
    如何生成8位随机字符密码?map 走起:
    • perl -le "print map { ('a'..'z')[rand 26] } 1..8"

      1..8 产生数组数字从 1-8,关键是产生8次循环
      ('a'..'z') 产生数组元素a-z,而 [rand 26] 随机产生数组下标,也就是随机选取字母
      map 返回每一次循环的处理结果

      要我写的话可能会用 grep ,逐个 print

      perl -e "grep { print (('a'..'z')[rand 26]) } (1..8)"

      发现 print ('a'..'z')[rand 26] 会提示语法问题,必须外加括号。
    累计文本中每行的首列数字的和
    • perl -lane "$sum += $F[0]; END { print $sum }" f.txt

      END {} 定义了一个代码块,该代码块在脚本结束时运行

      如果对 perl 的任一项参数有疑惑,可以参考
      perldoc perlrun

      其他参考
      perldoc perlvar - 关于 Perl 的特殊变量
      perldoc perlop - 操作符
      perldoc perlfunc - 函数
头像
523066680
Administrator
Administrator
帖子: 573
注册时间: 2016年07月19日 12:14
联系:

Chapter 2 - 换行和间隔符

帖子 523066680 »

Chapter 2 - 换行和间隔符
  • 在每行的末尾增加空白行
    • perl -pe "$\=\"\n\"" test.txt

      -p 和 -e 之前解释过了,以上代码相当于执行:
      while (<>) { $\ = "\n"; } continue { print or die "-p failed: $!\n"; }
      该循环将文件的每一行读取到 `$_`。特殊变量 `$\` 相当于 AWK 中的 ORS(Output Record Separator) 变量。其内容会被自动追加到 `$_` 的末尾,因此不需要在循环中反复执行 `$\ = "\n"`,将 `$\` 赋值放在 BEGIN 代码块即可(BEGIN代码块优先执行):

      perl -pe "BEGIN { $\=\"\n\" } " test.txt

      等效于下面代码:
      BEGIN { $\ = "\n" } while (<>) { } continue { print or die "-p failed: $!\n"; }
      也可以通过 "." 操作符连接:

      perl -pe "$_ .= \"\n\"" test.txt

      或者使用s///正则替换:

      perl -pe 's/$/\n/' test.txt

      甚至可以利用 say 操作符的特性(Perl 5.10 或以上):

      perl -nE 'say' test.txt

      -E 参数允许打开所有 Perl 的可选特性(为了支持 say 操作符)
      -n 参数类似 -p ,遍历所有读入的行但不主动 print(前面介绍过了)
      say 操作符类似 print,但 say 总是在每行的末尾添加 "\n"

      最后,别忘了多用 perldoc, 执行 perldoc perlrun 查看perl命令行参数的详细说明
    换行加倍,空行除外
    • perl -pe "$_ .= \"\n\" unless /^$/" test.txt

      unless 在 perl 中是 if not 的意思
      /^$/ 表示行的开头和末尾之间没有其他字符

      也可以用 \S 筛选:

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

      \s 代表一系列空白符号
      \S 表示空白以外的字符
      如果一行中包含空给以外的字符,则追加 \n
    三倍换行符
    • 相信各位已经能举一反三,就不细说了(后面的命令行示例省去文件名部分)

      perl -pe "$\ = \"\n\n\""

      perl -pe "$_ .= \"\n\n\""

      perl -pe "s/$/\n\n/"
    N倍换行符
    • Perl 使用 "字符"x数字 的方式翻倍地叠加字符,例如7个换行符:`"\n"x7`
    在每行之前添加空行
    • 使用正则替换向文件开头插入\n:

      perl -pe 's/^/\n/'
    删除空白行
    • perl -ne 'print unless /^$/'
      由于这里要自己判断(筛选)输出,所以使用 -n 而非 -p
[Finished in 1.6s]
回复

在线用户

正浏览此版面之用户: 没有注册用户 和 5 访客