如何让Perl脚本接受来自STDIN和命令行参数的参数?

时间:2014-12-03 04:48:39

标签: perl

受此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。

3 个答案:

答案 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

的输出

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;