簡體   English   中英

如何讓Perl腳本接受來自STDIN和命令行參數的參數?

[英]How can I get a Perl script to accept parameters from both STDIN and command line arguments?

受此U&L問答的啟發,標題為:“ 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。

我想出了以下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 ""

test.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

=====================================

參考

使用perl的鑽石操作員很容易做到這一點

push(@ARGV, "/dev/stdin");
while(<>) {
  print;
}

例如:

$ echo A > a
$ echo B > b
$ echo C | perl test.pl a b
A
B
C

不幸的是,這確實依賴於/dev/stdin ,但仍然相當便攜。

你可以在@ARGV的末尾添加STDIN輸入,

push @ARGV, <STDIN> unless -t STDIN;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM