Perl:如何在while循环中将行打印到文件中?

时间:2016-12-08 13:35:52

标签: perl while-loop

我有一个非常基本的perl脚本,它在匹配搜索模式后打印文本文件中的下一行。

@ARGV = <dom_boot.txt>;
while ( <> ) {
    print scalar <> if /name=sacux445/;
}

哪个有效,但是我想将输出捕获到文件中以供进一步使用,而不是将其打印到STDOUT。 我只是在学习(慢慢地),所以尝试了这个:

my $fh;
my $dom_bootdev = 'dom_bootdev.txt';

open ($fh, '>', $dom_bootdev) or die "No such file";

@ARGV = <dom_boot.txt>;
while ( <> ) {
    print $fh <> if /name=sacux445/;  
}

close $fh;

但是我收到语法错误。

  在try.plx第19行的

语法错误,靠近“&lt;&gt;”

我正在努力解决这个问题。我猜它可能非常简单,所以任何帮助都会受到赞赏。

谢谢, 路加。

3 个答案:

答案 0 :(得分:3)

Perl解析器有时会出现间接表示法的问题。处理它的规范方法是将句柄包装成一个块:

print {$fh} <> if /name=sacux445/;

您确定要删除scalar吗?

答案 1 :(得分:2)

如果线条匹配模式,只需获取循环中的下一行并打印它:

while (<>) {
  next unless /name=sacux445/;
  my $next = <>;
  last unless defined $next;
  print $fh $next;
}

注意,您需要检查菱形运算符的返回值。

输入

name=sacux445 (1)
aaa
name=sacux445 (2)
bbb
name=sacux445 (3)

输出

aaa
bbb

答案 2 :(得分:0)

应该学习使用状态机来解析数据。状态机允许输入读取仅在代码中的一个位置。将代码重写为状态机:

use strict;
use warnings;
use autodie; # See http://perldoc.perl.org/autodie.html

my $dom_bootdev = 'dom_bootdev.txt';
open ( my $fh, '>', $dom_bootdev ); # autodie handles open errors

use File::Glob qw( :bsd_glob ); # Perl's default glob() does not handle spaces in file names
@ARGV = glob( 'dom_boot.txt' );

my $print_next_line = 0;
while( my $line = <> ){

    if( $line =~ /name=sacux445/ ){
        $print_next_line = 1;
        next;
    }

    if( $print_next_line ){
        print {$fh} $line;
        $print_next_line = 0;
        next;
    }

}

何时使用状态机

如果数据是无上下文的,则只能使用正则表达式进行解析。

如果数据具有树结构,则可以使用简单的状态机对其进行解析。

对于更复杂的结构,至少需要一个带有下推式堆栈的状态机。堆栈记录先前的状态,以便当前状态结束时机器可以返回它。

使用的最复杂的数据结构是XML。它需要一个状态机来处理它的语法,第二个需要一个堆栈用于它的语义。