可以写一个perl脚本来接收来自(1)文 件,(2)stdin,(3)重定向中的任何一个的数据吗?

问题描述 投票:1回答:2

几个unix实用程序,如fmt,head和cat,可以通过以下3种方式之一接收数据:文件名;标准输入的管道;或重定向“<”。例如:

printf '%b' 'dog \ncat \nrat\n' > dogcatrat
fmt dogcatrat
cat dogcatrat  | fmt
fmt < dogcatrat

是否可以编写一个具有相同多功能性的perl脚本?或者有充分的理由不尝试这个吗?并且“管道来自标准输入”是指向以cat开头的代码行的正确方法吗?

我想写myfmt.pl,以这三种方式中的任何一种使用。

perl redirect pipe filenames
2个回答
5
投票

ARGV特殊文件句柄默认会这样做。它也是readline(也就是<><<>>操作符)在没有给出句柄时使用的句柄。所以这在Perl脚本中实际上很常见。

#!/usr/bin/env perl
use 5.022;
use warnings;
while (my $line = <<>>) {
  # $line from one of the filenames passed as an argument, otherwise STDIN
  # $ARGV is the current filename, or - when reading from STDIN
}

您可以使用<>运算符来支持旧版本的Perl,但<<>>运算符added in Perl 5.22是此任务的更好选项(如果可用),因为标准的<>运算符允许传递奇怪的东西,如date|来运行进程而不是读取文件。

为了在支持旧版本的Perl时更安全的文件名操作,您可以使用ARGV::readonly或模拟<<>>运算符,如下所示:

#!/usr/bin/env perl
use strict;
use warnings;
unshift @ARGV, '-' unless @ARGV;
while (my $file = shift) {
  my $fh;
  if ($file eq '-') {
    $fh = \*STDIN;
  } else {
    open $fh, '<', $file or die "open $file failed: $!";
  }
  while (my $line = <$fh>) {
    # ...
  }
}

(从技术上讲,<<>>操作符也不允许传递-作为读取STDIN的参数,但如果你想允许它,那么它是你的选择。)


1
投票

似乎以下脚本填写了账单。

#!/usr/bin/perl
use strict;
use warnings;
use 5.18.2;
local $/ = ""; # input record separator: one paragraph at a time
while (<>) {
    print;
    print "\n";
    say '-' x 30;
}

例:

printf '%b' 'dog \ncat \nrat\n' > aaa
try.pl aaa
cat aaa | try.pl
try.pl < aaa
© www.soinside.com 2019 - 2024. All rights reserved.