【问题标题】:Perl - How to omit lines from a text file?Perl - 如何从文本文件中省略行?
【发布时间】:2021-06-20 13:14:05
【问题描述】:

我有一个文本文件,我希望从文本文件中省略一些行,并使用该字符串创建一个新文件。好消息是我的文本文件以包含“START”并以“END”结尾的行开头我需要的文本块。

例如,我的文本文件如下所示:

1
2
3
Start
4
5
6
End
7
8
Start
9
10
End

所需的输出是两个字符串,我可以将它们输出到如下所示的文本文件中:

Start
4
5
6
End
Start
9
10
End

我目前拥有的:

open(RH, '<', $fileName) or die $!;

while(<RH>) {
    #print $_;
    chomp $_;
    if ($_ eq 'START') {
        $str = "$str"."$_\n";
    }
}

但我不确定如何继续。

编辑: 我使用以下方法回答了这个问题:

$cmd = q(awk '/Start/,/End/ {print}' foo.txt);
my $output = qx($cmd);
my @cards = split (/(?<=\End)/, $output);

【问题讨论】:

    标签: regex string perl


    【解决方案1】:

    您可以从 AWK 中使用 Perl 的一些遗产,然后执行此操作(假设您的文件名为 foo.txt)

    perl -ne'print if /Start/../End/' foo.txt
    

    表达式/Start/../End/ 的意思是“从匹配/Start/ 的第一行到匹配/End/ 的下一行。

    awk 的等效代码是

    awk '/Start/,/End/ {print}' foo.txt
    

    【讨论】:

    • 如果我想在我的 perl 脚本中使用这些行,我将如何使用它?
    • @NelsonSwasono 在另一篇与here 主题几乎相同的帖子中得到了回答。我不确定你为什么在说“谢谢”之后删除了该主题——通常,你会 accept the answer 并让它成为未来与你有同样问题的访问者的资源。考虑对这个线程和你提出的其他问题做同样的事情。
    【解决方案2】:
    # Read the entire file into a string `$str`:
    open my $fh, '<', 'file_name' or die "Can't open file $!";
    my $str = do { local $/; <$fh> };
    close $fh;
    
    while ($str =~ m{\n(START\n.*\nEND)\n}msg) {
        # Do something with each START...END set of lines
        print "$str\n";
    }
    

    注意事项:

    • 我不确定所有细节。
    • local $/;可能由 undef $/; 之类的东西完成
    • 调整括号以避免捕获“START”和“END”。

    【讨论】:

    • $/ = undef;undef $/; 好,local $/; 是本地化后最好的。
    • 不确定这是否正常工作。我假设您的代码示例打印出我想要的输出,但不幸的是,没有任何东西打印到终端。在 while 循环之前,文本文件被正确加载到 $str 中,但 while 循环不能正常运行。
    • @NelsonSwasono - 我对何时使用 /m 和 /s 感到困惑——删除任何一个。
    • 不幸的是,这仍然不起作用,您的示例中没有 /m 或 /s
    • @NelsonSwasono - TIMTOWTDI -- 我喜欢说=~ m{...} 而不是=~ /.../。这导致=~ m{...}msg 而不是=~ /.../msg
    【解决方案3】:

    使用 GNU grep

    grep -Poz '(?ms)^Start.*?^End\n' in_file
    

    这里,GNU grep 使用以下选项:
    -P:使用 Perl 正则表达式。
    -o:仅打印匹配项(每行 1 个匹配项),而不是整行。
    -z :将输入和输出数据视为行序列,每行都以零字节(ASCII NUL 字符)而不是换行符结尾。因此,您可以匹配输入中的换行符。

    (?ms) :分别启用ms pattern-match modifiers 以允许多行匹配,并允许. 匹配换行符。

    另请参阅:
    grep manual
    perlre - Perl regular expressions

    【讨论】:

      【解决方案4】:

      使用.. 作为“触发器”运算符。

      # Switch to a lexical filehandle
      # (as this is modern best practice)
      open(my $rh, '<', $fileName) or die $!;
      
      # Open an output filehandle
      my $x = 1;
      open my $out, '>', "$filename.out.$x" or die $!;
      
      while(<$rh>) {
        print $out $_ if /Start/ .. /End/;
      
        # Open a new output file if we've seen 'End'
        if (/End/) {
          ++$x;
          open my $out, '>', "$filename.out.$x" or die $!;
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-12-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-20
        • 2016-06-30
        • 2012-06-09
        • 2015-01-08
        相关资源
        最近更新 更多