几个unix实用程序,如fmt,head和cat,可以通过以下3种方式之一接收数据:文件名;标准输入的管道;或重定向“<”。例如:
printf '%b' 'dog \ncat \nrat\n' > dogcatrat
fmt dogcatrat
cat dogcatrat | fmt
fmt < dogcatrat
是否可以编写一个具有相同多功能性的perl脚本?或者有充分的理由不尝试这个吗?并且“管道来自标准输入”是指向以cat开头的代码行的正确方法吗?
我想写myfmt.pl,以这三种方式中的任何一种使用。
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的参数,但如果你想允许它,那么它是你的选择。)
似乎以下脚本填写了账单。
#!/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