【问题标题】:Can we do this in perl?我们可以在 perl 中做到这一点吗?
【发布时间】:2020-06-07 23:53:00
【问题描述】:

我希望将下面的 awk 单行代码翻译成 perl。有可能吗??

awk '{ for(i=1;i<=NF;i++){if(i==NF){printf("%s\n",$NF);}else {printf("%s\t",$i)}}}' file.txt |  awk 'NR > 1'

第一个 awk 命令删除前导空列,下一个删除第一行。 下面是file.txt的头部

#FILEOUTPUT
       1    137442      2324
    2326    139767      4169
    6491    143936        94

我从这些命令得到的输出如下

1       137442  2324
2326    139767  4169
6491    143936  94

谢谢, 卡西克

【问题讨论】:

  • 请解释一下这个命令的作用。您还可以在 perl 中使用 system(" ") 来执行相同的 shell 命令。不需要转换。但如果这是要求,请让我们知道 file.txt 包含的内容以及您想要的输出。
  • 这一行相当于:awk 'BEGIN{OFS="\t"}{$1=$1}(FNR&gt;1 &amp;&amp; NF)' file
  • perl -lane 'print join("\t", @F) if $. &gt; 1 &amp;&amp; @F' file.txt
  • 看看从 awk 迁移,例如这个part of a tutorial book.
  • fwiw,你可以在 awk 中使用 awk -v OFS='\t' 'BEGIN{getline}{$1=$1}1' 更轻松地做到这一点,它被翻译成 perl 得到 perl -anle 'BEGIN{&lt;&gt;;$,="\t"}print@F'。与 perl -nperl -p 一样,请注意 perl 解释“有趣”文件名,如 &gt;/etc/passwd

标签: linux perl awk


【解决方案1】:

@Alex 正确地使用了$.——这不是一个非常常见的 perl 习惯用法(尽管我们看到它很有用),但是他们没有正确处理多余的空格。

Awk 就是要了解字段是什么,然后操作字段,作为其中的一部分,它会进行大量空白规范化。

OTOH 的 Perl 通常不涉及字段分离,而且很多用户自己喜欢这样做 - 但它使用 -a 标志支持这种 Awk 行为。

因此,上述 Awk 线路噪声的简单实现可能如下所示:

perl -anle 'print join("\t",@F) if $. > 1' file.txt

解释:

  • -a:使用默认字段分隔符(在这种情况下效果很好)或 -F 所说的任何内容(如 Awk)触发字段分隔。
  • -n :遍历输入行(与最外面的 {} 在 Awk 中所做的相同)。一个常见的替代方案是-p,这意味着迭代输入行,然后在运行代码后打印出行缓冲区中的任何内容。
  • -l :打印时,在文本末尾添加一个新行(让这样的事情更容易处理)
  • -e:这是一个脚本。

然后我们只需将分离的字段数组(@F)加入它。开发人员通常喜欢使用 $F[&lt;index&gt;] 来处理某些字段,但在这里我们不需要循环 - 我们可以按原样获取列表并将其通过管道传输到 join()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-10-27
    • 1970-01-01
    • 2015-04-11
    • 1970-01-01
    • 2011-03-08
    • 2011-01-30
    • 1970-01-01
    • 2023-03-28
    相关资源
    最近更新 更多