受此U& L Q& A标题为“https://unix.stackexchange.com/questions/171150/back-to-back-pipes-into-a-command”的启发。如何通过STDIN和命令行参数解析输入到Perl脚本?
例如,我想要一个可以使用STDIN和命令行参数的输入参数的脚本:
$ command | my_command.pl arg1 arg2
command
的输出将是
arg3
arg4
...
所以当my_command.pl
运行时,它会知道参数arg1,arg2,arg3和arg4。
答案 0 :(得分:3)
我想出了以下Perl脚本,该脚本从STDIN或命令行参数中读取数据,或者两者都读取。
$ cat command.pl
#!/usr/bin/perl -w
use strict;
if ( -t STDIN and not @ARGV ) {
print "\n" ."USAGE" . "\n";
print "=====" . "\n";
print "#1:\t $0 <arg1>..<argN>\n";
print "#2:\t <commands> | $0\n";
print "#3:\t <commands> | $0 <arg1>..<argN>\n\n";
exit 1;
}
if ( not -t STDIN ) {
print "\n" . "STDIN ARGS" . "\n";
print "==========" . "\n";
print while (<STDIN>);
print "\n";
}
if (@ARGV) {
print "\n" . "ARGV ARGS" . "\n";
print "=========" . "\n";
foreach (@ARGV) {
print "$_\n";
}
print "\n";
}
该脚本同时使用@ARGV
和<STDIN>
,并确定它们是否已定义。如果两者都没有定义,那么它会显示使用情况并退出。
为了测试它,我把这个名为tests.bash
的辅助脚本放在一起,它使用各种方法运行上述脚本以将输入传递给它。 注意:测试标记为T00到T10。
$ cat tests.bash
#!/bin/bash
echo ""
echo ""
echo "====================================="
echo "T00: no input"
./command.pl
echo "====================================="
echo ""
# http://www.tldp.org/LDP/abs/html/subshells.html
echo "====================================="
echo "T01: 2 args w/ pipe via cmd list '(..) | ...' aka. subshell"
( echo "pipearg1"; echo "pipearg2"; ) | ./command.pl
echo "====================================="
echo ""
# http://www.tldp.org/LDP/abs/html/special-chars.html#CODEBLOCKREF
echo "====================================="
echo "T02: 2 args w/ pipe via inline group '{..} | ...' aka. code block"
{ echo "pipearg1"; echo "pipearg2"; } | ./command.pl
echo "====================================="
echo ""
echo "====================================="
echo "T03: 2 cli args 'cmd A1 A2'"
./command.pl argv1 argv2
echo "====================================="
echo ""
echo "====================================="
echo "T04: T01 + T03"
( echo "pipearg1"; echo "pipearg2"; ) | ./command.pl argv1 argv2
echo "====================================="
echo ""
echo "====================================="
echo "T05: T02 + T03"
{ echo "pipearg1"; echo "pipearg2"; } | ./command.pl argv1 argv2
echo "====================================="
echo ""
echo "====================================="
echo "T06: echo with newline: $'..\n..'"
echo $'pipearg1\npipearg2' | ./command.pl
echo "====================================="
echo ""
echo "====================================="
echo "T07: echo -e with newline: '..\n..'"
echo -e "pipearg1\npipearg2" | ./command.pl
echo "====================================="
echo ""
echo "====================================="
echo "T08: 2 cli args via HEREDOC 'cmd <<EOF ... EOF'"
./command.pl <<EOF
arghd1
arghd2
EOF
echo "====================================="
echo ""
echo "====================================="
echo "T09: 2 cli args via process substitution 'cmd < <(...cmds...)'"
./command.pl < <(echo argps1; echo argps2)
echo "====================================="
echo ""
echo "====================================="
echo "T10: T03 + T09"
./command.pl argv1 argv2 < <(echo argps1; echo argps2)
echo "====================================="
echo ""
tests.bash
脚本旨在运行11种不同的测试,从使用HEREDOCS到子shell,再到传递命令行参数。它还结合使用这些来完全测试Perl脚本command.pl
。
$ ./tests.bash
=====================================
T00: no input
USAGE
=====
#1: ./command.pl <arg1>..<argN>
#2: <commands> | ./command.pl
#3: <commands> | ./command.pl <arg1>..<argN>
=====================================
=====================================
T01: 2 args w/ pipe via cmd list '(..) | ...' aka. subshell
STDIN ARGS
==========
pipearg1
pipearg2
=====================================
=====================================
T02: 2 args w/ pipe via inline group '{..} | ...' aka. code block
STDIN ARGS
==========
pipearg1
pipearg2
=====================================
=====================================
T03: 2 cli args 'cmd A1 A2'
ARGV ARGS
=========
argv1
argv2
=====================================
=====================================
T04: T01 + T03
STDIN ARGS
==========
pipearg1
pipearg2
ARGV ARGS
=========
argv1
argv2
=====================================
=====================================
T05: T02 + T03
STDIN ARGS
==========
pipearg1
pipearg2
ARGV ARGS
=========
argv1
argv2
=====================================
=====================================
T06: echo with newline: $'..\n..'
STDIN ARGS
==========
pipearg1
pipearg2
=====================================
=====================================
T07: echo -e with newline: '..\n..'
STDIN ARGS
==========
pipearg1
pipearg2
=====================================
=====================================
T08: 2 cli args via HEREDOC 'cmd <<EOF ... EOF'
STDIN ARGS
==========
arghd1
arghd2
=====================================
=====================================
T09: 2 cli args via process substitution 'cmd < <(...cmds...)'
STDIN ARGS
==========
argps1
argps2
=====================================
=====================================
T10: T03 + T09
STDIN ARGS
==========
argps1
argps2
ARGV ARGS
=========
argv1
argv2
=====================================
答案 1 :(得分:2)
使用perl diamond operator
这很容易push(@ARGV, "/dev/stdin");
while(<>) {
print;
}
例如:
$ echo A > a
$ echo B > b
$ echo C | perl test.pl a b
A
B
C
不幸的是,这确实依赖于/dev/stdin
,但仍然相当便携。
答案 2 :(得分:1)
您可以在STDIN
,
@ARGV
的输入
push @ARGV, <STDIN> unless -t STDIN;