解析行时将输入记录分隔符更改为\ n或\ r \ n

时间:2014-03-03 20:16:10

标签: perl

我有一个perl脚本,它从另一个进程读取输出(逐行),进行一些处理并吐出结果:

#!/bin/bash 
set -e
set -o pipefail

RUN.SH ${@} 2>&1 | perl -M"Term::ANSIColor" -wnl -e '
m/ERROR/i and print "\e[1;91m", "$_", "\e[0m" 
or print;'

除非流程RUN.SH的输出不以新行(\n结尾)结束,而是以\r结尾,否则效果很好!在这种情况下,此Perl解析器在下一个\n之前不会打印任何内容。我需要更改它,以便它同时使用\n\r作为输入记录分隔符。

有什么想法吗?

3 个答案:

答案 0 :(得分:3)

有四种方法可以从文件中读取:

  • 一次一个字符:getc
  • 一次一行:readline $/ = $terminator;
  • 一次一个街区:readreadline $/ = \$length;
  • 数据到达时:sysread

getc可行,但我会使用效率更高的sysread

perl -we'
   sub make_iter {
      my ($fh) = @_;

      my $buf = "";
      my $eof = 0;

      return sub {
         return if $eof;

         while (1) {
            return $1 if $buf =~ s/^([^\r\n]*[\r\n])//;

            my $rv = sysread(STDIN, $buf, 64*1024, length($buf));
            if (!$rv) {
               $eof = 1;
               die $! if !defined($rv);
               return $buf if length($buf);
               return;
            }
         }
      };
   }

   binmode(STDIN);
   binmode(STDOUT);
   $| = 1;

   my $iter = make_iter(\*STDIN);
   while (my ($line) = $iter->()) {
      $line = "\e[1;91m" . $line . "\e[0m" if $line =~ /ERROR/i;
      print($line);
   }
'

答案 1 :(得分:0)

只需插入替换管段:

... | perl -pe's / \ r / \ n / g'| ...

RUN.SH ${@} 2>&1 | perl -pe 's/\r/\n/g' | perl -M"Term::ANSIColor" -wnl -e '
m/ERROR/i and print "\e[1;91m", "$_", "\e[0m" 
or print;'

试验:

ivr@linux-e8sg:~> echo -e 'a\nb\rc\n'
a
c

ivr@linux-e8sg:~> echo -e 'a\nb\rc\n'  | perl -pe 's/\r/\n/g'
a
b
c

答案 2 :(得分:-4)

哦,男孩,很多伟大而奇妙的剧本不正确。

'$ INPUT_RECORD_SEPARATOR'更改此默认值为'\ n'您可以在perl脚本本身中将其更改为您需要的内容。

您可以在perl special variables阅读更多内容,使用网络浏览器查找并搜索“INPUT_RECORD_SEPARATOR”