【问题标题】:Removing lines containing a string from a file w/ perl从带有 perl 的文件中删除包含字符串的行
【发布时间】:2013-10-27 17:37:19
【问题描述】:

我正在尝试获取文件 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(&lt;INPUT&gt;) 应该一次读取一行(如果我的理解正确的话)并将每一行存储在特殊变量$_

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

我想做的是得到一条线,测试它,用它做点什么,然后继续下一条。

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

我已经尝试了此代码的其他一些变体,但我认为这是我最接近的。我认为我没有得到我期望的行为是有充分理由的,谁能告诉我这是什么?

【问题讨论】:

  • 你能检查以下几行的输出吗? @lines = &lt;INPUT&gt;; print scalar @lines;
  • @jkshah = 它返回了一个,直到我在这里给出了一些其他提示来修复它。

标签: perl


【解决方案1】:

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

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

关于您的代码的一些注释:

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

无需切掉你不使用的线。

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

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

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

无需删除换行符然后将它们放回原处。此外,通常您会使用\n 作为行尾,即使在 Windows 上也是如此。

而且,由于您在每个 if-else 子句中都大吃一惊,您不妨将其移到整个 if-block 之外。

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 $_;
}

【讨论】:

  • 它是#1,或者更具体地说,不是#1。我期待 \n 就像你说的那样结束,由于某种原因它是 \r。即使我会意识到这一点,但我可能不知道要重置什么。感谢您提供的其他提示,我知道我还有很多需要改进的地方。
猜你喜欢
  • 2020-01-03
  • 2014-04-24
  • 2021-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-31
  • 1970-01-01
相关资源
最近更新 更多