使用 Perl 单线就地编辑时使用 begin 块

Posted

技术标签:

【中文标题】使用 Perl 单线就地编辑时使用 begin 块【英文标题】:Using begin block while editing in place with Perl one-liner 【发布时间】:2013-12-18 10:37:01 【问题描述】:

我正在尝试让 Perl 单线工作:

$ perl -aln -F"\t" -i -e 'BEGINprint qq(taxid:int:ncbitaxid\tname\tl:label) print qq($F[0]\t$F[1]\trank,$F[2])' testing

用于测试的输入文件如下所示:

1    root    no rank
2    Bacteria    superkingdom
6    Azorhizobium    genus
7    Azorhizobium caulinodans    species
9    Buchnera aphidicola    species
10    Cellvibrio    genus
11    [Cellvibrio] gilvus    species
13    Dictyoglomus    genus
14    Dictyoglomus thermophilum    species
16    Methylophilus    genus

所需的输出如下所示:

taxid:int:ncbitaxid    name    l:label
1    root    rank,no rank
2    Bacteria    rank,superkingdom
6    Azorhizobium    rank,genus
7    Azorhizobium caulinodans    rank,species
9    Buchnera aphidicola    rank,species
10    Cellvibrio    rank,genus
11    [Cellvibrio] gilvus    rank,species
13    Dictyoglomus    rank,genus
14    Dictyoglomus thermophilum    rank,species
16    Methylophilus    rank,genus

我已经能够使用以下内容重新创建它,但我想就地编辑,而不是打印到另一个文件。

perl -aln -F"\t" -e 'BEGINprint qq(taxid:int:ncbitaxid\tname\tl:label) print qq($F[0]\t$F[1]\trank,$F[2])' testing

【问题讨论】:

你得到的错误是什么? 那么……有什么问题?? @qwrrty:问题是 BEGIN 中的打印发生在就地编辑之前 @ysth 感谢您的澄清 +1 【参考方案1】:

见perlrun, the -i switch for in-place editing。

见perlvar, $. line number for the last filehandle accessed。

perl -aln -i.bak -F"\t" -e 'print qq(taxid:int:ncbitaxid\tname\tl:label) if $.==1; \
                            print qq($F[0]\t$F[1]\trank,$F[2])' testing

【讨论】:

嗨 codnodder 感谢您的建议,我只是想知道为什么 print qq(taxid:int:ncbitaxid\tname\tl:label) if $.==1; 中的标签后不需要换行符 @altimit -l 开关提供自动行结束处理。见perlrun, the -l switch。 -l 开关 启用自动行结束处理。它有两个不同的效果。首先,当与 -n 或 -p 一起使用时,它会自动选择 $/(输入记录分隔符)。其次,它指定 $\(输出记录分隔符)具有 octnum 的值,以便任何打印语句都会重新添加该分隔符。如果省略 octnum,则将 $\ 设置为 $/ 的当前值。 @altimit 是的,就是这样。附带说明一下,在您的情况下,输入行尾处理有些无关紧要,因为您使用-a 在空格上进行拆分,因此您的单行代码无论如何都会忽略尾随空格。【参考方案2】:

为in place editing 使用-i 开关:

perl -i -aln -F"\t" -e'
  print qq(taxid:int:ncbitaxid\tname\tl:label) if $. ==1;
  print qq($F[0]\t$F[1]\trank,$F[2])
' testing

-i[扩展名] 指定由 构造处理的文件将被就地编辑。它通过重命名输入文件、按原始名称打开输出文件并选择该输出文件作为 print() 语句的默认值来实现此目的。

【讨论】:

同意您的-i 建议,但我认为-i 和使用BEGIN 块之间可能存在不正确的交互。默认的输出文件句柄还没有指向正在编辑的文件句柄,所以在这种情况下,它只是将标题行打印到 STDOUT 而不是正在编辑的文件。如果我不正确,请随时纠正我。 @mpapec

以上是关于使用 Perl 单线就地编辑时使用 begin 块的主要内容,如果未能解决你的问题,请参考以下文章

您最新的有用 Perl 单线(或涉及 Perl 的管道)是啥? [关闭]

使用 Best In Place gem,我如何允许就地编辑链接?

就地编辑内容编辑

作为sed替代方案的Perl就地替换

解析Perl 5并检查语法树

使用闭包修改 Perl BEGIN 块中的类