Perl - 如何从文本文件中省略行?

Perl - How to omit lines from a text file?

我有一个文本文件,我想从文本文件中省略一些行,并使用该字符串创建一个新文件。好消息是我的文本文件以包含“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);

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

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

表达式 /Start/../End/ 表示“从匹配 /Start/ 的第一行到匹配 /End/.

的下一行

awk 的等效代码是

awk '/Start/,/End/ {print}' foo.txt
# 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'。

使用 GNU grep:

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

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

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

另见:
grep manual
perlre - Perl regular expressions

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

# 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 $!;
  }
}