简体   繁体   English

如何使用Perl读取文件中两行之间的所有行?

[英]How can I read all of the lines between two lines in a file, using Perl?

I have one file where the contents looks like: 我有一个文件的内容如下:

pch
rch
channel
cap
nch
kappa
.
.
.
kary
ban
....

Now I want to read my file from nch to kary and copying those lines only in some other file. 现在我想从nch读取我的文件到kary并仅在其他文件中复制这些行。 How can I do this in Perl? 我怎么能在Perl中做到这一点?

If I understand your question correctly, this is pretty simple. 如果我理解你的问题,这很简单。

    #!perl -w
    use strict;
    use autodie;

    open my $in,'<',"File1.txt";
    open my $out,'>',"File2.txt";

    while(<$in>){
    print $out $_ if /^nch/ .. /^kary/;
    }

From perlfaq6 's answer to How can I pull out lines between two patterns that are themselves on different lines? perlfaq6的答案我怎样才能在不同线条上的两个模式之间拉出线条?


You can use Perl's somewhat exotic .. operator (documented in perlop): 你可以使用Perl有点奇特的运算符(在perlop中记录):

perl -ne 'print if /START/ .. /END/' file1 file2 ...

If you wanted text and not lines, you would use 如果你想要文字而不是线条,你会使用

perl -0777 -ne 'print "$1\n" while /START(.*?)END/gs' file1 file2 ...

But if you want nested occurrences of START through END, you'll run up against the problem described in the question in this section on matching balanced text. 但是,如果您希望嵌套出现START到END,那么您将遇到本节中有关匹配平衡文本的问题中描述的问题。

Here's another example of using ..: 这是使用..的另一个例子:

while (<>) {
    $in_header =   1  .. /^$/;
    $in_body   = /^$/ .. eof;
# now choose between them
} continue {
    $. = 0 if eof;  # fix $.
}

You could use this in 'sed': 你可以在'sed'中使用它:

sed -n /nch/,/kary/p $file

You could use 's2p' to convert this to Perl. 您可以使用's2p'将其转换为Perl。

You could also write pure Perl: 你也可以编写纯Perl:

while (<>)
{
    next unless /nch/;
    print;
    while (<>)
    {
        print;
        last if /kary/;
    }
}

Strictly, both these solutions will print each set of lines from 'nch' to 'kary'; 严格来说,这两种解决方案都会打印从'nch'到'kary'的每一行。 if 'nch' appears more than once, it will print more than one chunk of code. 如果'nch'出现不止一次,它将打印多个代码块。 It is easy to fix that, especially in the pure Perl ('sed' solution left as an exercise for the reader). 这很容易解决,特别是在纯粹的Perl中('sed'解决方案留给读者练习)。

OUTER:
while (<>)
{
    next unless /nch/;
    print;
    while (<>)
    {
        print;
        last OUTER if /kary/;
    }
}

Also, the solutions look for 'nch' and 'kary' as part of the line - not for the whole line. 此外,解决方案寻找'nch'和'kary'作为线的一部分 - 而不是整条线。 If you need them to match the whole line, use ' /^nch$/ ' etc as the regex. 如果你需要它们来匹配整行,使用' /^nch$/ '等作为正则表达式。

Something like: 就像是:

$filter = 0;
while (<>) {
  chomp;
  $filter = 1 if (! $filter && /^nch$/);
  $filter = 0 if ($filter && /^ban$/);
  print($_, "\n") if ($filter);
}

should work. 应该管用。

if you only want to read one block, in gawk 如果你只想读一个街区,那就是gawk

gawk '/kary/&&f{print;exit}/nch/{f=1}f' file

in Perl 在Perl

perl -lne '$f && /kary/ && print && exit;$f=1 if/nch/; $f && print' file

or 要么

while (<>) {
    chomp;
    if ($f && /kary/) {
        print $_."\n";
        last;
    }
    if (/nch/) { $f = 1; }
    print $_ ."\n" if $f;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM