如何在多行文件中输出第二行

时间:2013-08-31 17:54:35

标签: perl

我有一个重复行的大文件如下:

@UUSM
ABCDEADARFA
+------qqq
!2wqeqs6777

我想输出文件中的所有“第二行”。我执行此操作时会剪切以下代码,但它没有按预期工作。第1,3和4行代替输出。

open(IN,"<", "file1.txt") || die "cannot open input file:$!";
while (<IN>) {
$line = $line . $_;
if ($line =~ /^\@/) { 
    <IN>;
    #next;
    my $line = $line; 
    }
}
print "$line";

请帮忙!

4 个答案:

答案 0 :(得分:1)

试试这个

open(IN,"<", "file1.txt") || die "cannot open input file:$!";
my $lines = "";

while (<IN>) {
 if ($. % 4 == 2) $lines .= $_;
}

print "$lines";

答案 1 :(得分:1)

perl -ne '$at = $. if /^\@/; print if $. - 1 == $at' file1.txt

写出来,上面相当于

open my $fh, "<", "file1.txt";

my $at_line = 0;
while (<$fh>) {
    if (/^\@/) {
      $at_line = $.;
    }
    else {
      print if $. - 1 == $at_line;
    }
}

答案 2 :(得分:1)

我假设您要问的是如何打印以@开头的行之后的行:

perl -ne 'if (/^\@/) { print scalar <> }' file1.txt

这说,“如果该行以@开头,则打印下一行。对参数列表中的所有文件执行此操作。”这里使用scalar函数在文件句柄上施加标量上下文,这样它就不会打印整个文件。默认情况下,print具有其参数的列表上下文。

如果你真的想在文件中打印第二行,那就更容易了。以下是一些例子:

使用行号$.变量,如果它等于第2行,则打印。

perl -ne '$. == 2 and print, close ARGV' yourfile.txt

请注意,如果您有多个文件,则必须关闭ARGV文件句柄才能重置计数器$.。另请注意,使用较低优先级运算符and会强制printclose都绑定到条件。

使用常规逻辑。

perl -ne 'print scalar <>; close ARGV;'
perl -pe '$_ = <>; close ARGV;' 

在打印第二行时,通过关闭ARGV文件句柄,这两个都使用了短路功能。如果您想要打印文件的每隔一行,如果您删除close语句,这两个行都会这样做。

答案 3 :(得分:0)

如果你想要打印第2,6,10行,那么:

while (<>)
{
    print if $. % 4 == 2;
}

$.是当前行号 - 我没有花时间打开和关闭文件。那可能是:

{
    my $file = "file1.txt";
    open my $in, "<", $file or die "cannot open input file $file: $!";
    while (<$in>)
    {
        print if $. % 4 == 2;
    }
}

这使用现代首选形式的文件句柄(词法文件句柄),构造周围的大括号意味着文件句柄自动关闭。无法打开的文件的名称包含在错误消息中;使用or运算符,因此优先级正确(原语中的括号和||也很好,可以在这里使用,但通常不是)。

如果您希望打印以@开头的行后的行,则必须采用不同的方式组织。

my $print_next = 0;
while (<>)
{
    if ($print_next)
    {
        print $_;
        $print_next = 0;
    }
    elsif (m/^@/)
    {
        $print_next = 1;
    }
}

解析问题中的代码

问题中代码的原始版本是(为方便起见添加了行号):

 1   open(IN,"<", "file1.txt") || die "cannot open input file:$!";
 2   while (<IN>) {
 3   $line = $line . $_;
 4   if ($line =~ /^\@/) {
 5       <IN>;
 6       #next;
 7       my $line = $line;
 8       }
 9   }
10   print "$line";

讨论每一行:

  1. 好的,虽然它不使用词法文件句柄或报告无法打开哪个文件。
  2. 行。
  3. 过早和误入歧途。在完成任何分析之前,这会将当前行添加到变量$line。如果需要,可以写成$line .= $_;
  4. 建议所需输出的正确描述不是“第二行”,而是“以@开头的行之后的行。请注意,由于正则表达式上没有多行修饰符,因此它始终只匹配变量$line中的第一个线段。由于过早连接,它将在每一行上匹配(因为第一行数据以@开头),执行第5-8行中的代码。
  5. 将另一行读入$_。它没有测试EOF,但那是无害的。
  6. 评论专栏;除了提出一些混淆之外没有任何意义。
  7. my $line = $line;是一个隐藏外部$line的新变量的自我赋值...主要是怪异,在较小程度上它是一个没有 - 运。您没有使用use strict;use warnings;,因为如果您这样做,您会收到警告。 Perl专家使用use strict;use warnings;来确保他们没有犯过愚蠢的错误;新手应该出于同样的原因使用它们。
  8. 本身,好的。但是,条件中的代码并没有真正完成。它会跳过文件中的第二行;它稍后会跳过第四,第六,第八等等。
  9. 行。
  10. 好的,但是......如果您只想在行@之后打印行,或者只对打印行号为2N + 2的整数N感兴趣,那么就没有必要在打印每一行之前在内存中构建整个字符串。打印出需要打印的每一行都会更简单。