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

Posted

技术标签:

【中文标题】Perl - 如何从文本文件中省略行?【英文标题】:Perl - How to omit lines from a text file? 【发布时间】: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);

【问题讨论】:

【参考方案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)\nmsg) 
    # 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 manualperlre - 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 $!;
  

【讨论】:

以上是关于Perl - 如何从文本文件中省略行?的主要内容,如果未能解决你的问题,请参考以下文章

从 Perl 中的文本文件读取时跳过标题的最佳方法是啥?

如何将控制台输出重定向到文本文件

从包含可变数据的文件中删除静态文本块

如何检查一个文件的值是不是包含在另一个文本文件中? (perl 脚本)

如何在 perl 中发送 HTML/纯文本邮件

在perl中重新加载页面时如何显示文本文件中的随机数据?