使用/ perl从文件中删除包含字符串的行

时间:2013-10-18 18:53:31

标签: perl

我正在尝试接收一个文件INPUT,如果该文件中的一行包含一个字符串,则将该行替换为其他内容(整行,包括换行符),或者根本不替换任何内容(删除它之类的行)不在那里)。将所有这些写入新文件。

以下是该部分代码......

while(<INPUT>){
    if ($_ =~ /  <openTag>/){
        chomp;
        print OUTPUT "Some_Replacement_String";
    } elsif ($_ =~ /  <\/closeTag>/) {
        chomp;
        print OUTPUT ""; #remove the line
    } else {
        chomp;
        print OUTPUT "$_\r\n"; #print the original line
    }
}

while(<INPUT>)应该一次读一行(如果我的理解是正确的)并将每一行存储在特殊变量$_

然而,当我运行上面的代码时,我只得到第一个if语句条件返回Some_Replacement_String,并且只返回一次。 (1行,一个1.3米的文件,预计有600,000个替换)。这显然不是我期望的行为。如果我执行while(<INPUT>){print OUTPUT $_;)之类的操作,我会获得整个文件的副本,每行,所以我知道正在读取整个文件(预期的行为)。

我要做的是获得一条线,测试它,用它做一些事情,然后继续下一个。

如果它对故障排除有帮助,如果我在while语句(或之后)的任何地方使用print $.;,我会返回1。我希望这是“访问的最后一个文件句柄的当前行号”。所以当我的while语句遍历整个文件时,它应该等于文件中的行数,而不是1。

我已尝试过此代码的其他一些变体,但我认为这是我最接近的。我假设有一个很好的理由我没有得到我期望的行为,有人能告诉我它是什么吗?

1 个答案:

答案 0 :(得分:4)

您描述的问题表明您的输入文件只包含一行。这可能是因为许多不同的事情,例如:

  • 您已更改输入记录分隔符$/
  • 您的输入文件不包含正确的行结尾
  • 您正在使用-0777开关
  • 运行脚本

关于您的代码的一些注意事项:

if ($_ =~ /  <openTag>/){
    chomp;
    print OUTPUT "Some_Replacement_String";

无需选择您未使用的线路。

} elsif ($_ =~ /  <\/closeTag>/) {
    chomp;
    print OUTPUT "";

这是多余的。你不需要打印一个空字符串(永远,真的),并选择你没有使用的值。

} else {
    chomp;
    print OUTPUT "$_\r\n"; #print the original line

无需删除新行,然后将其删除。此外,通常您会使用\n作为行结尾,即使在Windows上也是如此。

而且,既然你在每个if-else子句中咀嚼,你也可以将它移到整个if块之外。

chomp;
if (....) {

但是既然你不依赖于不在那里的行结尾,为什么还要费心使用chomp呢?

使用$_变量时,您可以缩写某些命令,例如您使用chomp。例如,单独的正则表达式将应用于$_

} elsif (/  <\/closeTag>/) {  # works splendidly

如上所述,当你有一个包含斜杠的正则表达式时,你可以为正则表达式选择另一个分隔符,这样你就不需要转义斜杠:

} elsif (m#  </closeTag>#) {

但是,您需要使用m//运算符的完整表示法,前面有m

所以,简而言之

while(<INPUT>){
    if (/  <openTag>/){
        print OUTPUT "Some_Replacement_String";
    } elsif (m#  </closeTag>#) {
        # do nothing
    } else {
        print OUTPUT $_;   # print the original line
    }
}

当然,最后两个可以组合成一个,带有一些否定逻辑:

} elsif (not m#  </closeTag>#) {
    print OUTPUT $_;
}