perl替换多个文件中的字符串

时间:2013-10-16 15:11:19

标签: regex perl

我正在尝试替换多个文件中的字符串。但只有第一个文件被替换。代码是:

perl -pi -e 's/(^<section_begin>.*\s+$)/\1<expand>\n/ if $.==1' *exp`

grep -iw "expand" *exp
a3exp:<expand>

如果我对单个文件使用相同的命令,它正在工作:

perl -pi -e 's/(^<section_begin>.*\s+$)/\1<expand>\n/ if $.==1' n2exp
grep -iw "expand" *exp
a3exp:<expand>
n2exp:<expand>

你能帮我解决这个问题吗?

5 个答案:

答案 0 :(得分:4)

根据perlvar

  

$。文件句柄关闭时重置,但重新打开文件句柄时没有插入关闭(),

     

因为&#34;&lt;&gt;&#34;从不在ARGV文件中明确关闭,行数增加(但请参阅eof中的示例)。

(第二个重点补充)

使用-p时,@ARGV设置为您在命令行上传递的文件列表。由于在转到下一个文件时未重置$.,因此对于第一个文件,它仅等于1。您只需打印$.

即可看到此信息
$ echo foo > foo
$ echo bar > bar
$ perl -pe 'print "$. "' *
1 bar
2 foo

-p行自动打印,因此在上面的示例中,每行的内容都打印在$.)的旁边

当您mpapec suggests移动到下一个文件时close特殊文件句柄ARGV$.将按您的预期行事:

$ perl -pe 'print "$. "; close ARGV if eof' *
1 bar
1 foo

有关更多详细信息和一些很好的示例,请参阅documentation for eof

答案 1 :(得分:3)

关闭ARGV文件句柄后,行计数器$.会重置。

http://perldoc.perl.org/perlvar.html#ARGV

  

在@ARGV

中迭代命令行文件名的特殊文件句柄

因此,您需要在到达eof()时明确关闭文件,

perl -pi -e'
  s/(^<section_begin>.*\s+$)/\1<expand>\n/ if $.==1;
  close ARGV if eof;
' *exp

答案 2 :(得分:2)

Unix shell有很多工具可以解决这个问题。有find的{​​{1}}:

-exec

或老式的find . -name \*exp -exec perl -pi -e '... if $.==1' {} \; 循环。在for中看起来像

bash

答案 3 :(得分:2)

您可以使用eofeof(ARG)检测每个文件的结尾并重置$.

来自文档

  

在while(&lt;&gt;)循环中,eof或eof(ARGV)可用于检测每个文件的结尾,而eof()将仅检测最后一个文件的结尾。例子:

# reset line numbering on each input file
while (<>) {
    next if /^\s*#/;  # skip comments
    print "$.\t$_";
} continue {
    close ARGV if eof;  # Not eof()!
}

http://perldoc.perl.org/functions/eof.html

答案 4 :(得分:0)

我认为你的if。== 1会让你。处理了这些行:你告诉它只处理输入的第一行。