如何在perl脚本中检查管道数据

时间:2015-05-24 23:36:48

标签: linux bash perl shell stdin

我目前正在使用这两个if语句来决定数据是通过管道输入还是来自文件:

pod2usage("$NAME: Requires at least one argument FILE.\n") if ((-t STDIN) && (@ARGV == 0));
pod2usage("$NAME: zero if input is from STDIN.\n") if (!(-t STDIN) && (@ARGV != 0));

当perl脚本从shell以交互方式运行时,这很好用。例如,这些按预期工作:

$ perl_script <flags> filename
$ cat | perl_script <flags>

但是,当从一个bash脚本或者emacs中的org-mode之类的东西调用perl脚本时,脚本会认为它正在管理数据并在文件作为参数提供时抛出pod2usage错误。以下是导致此行为的示例:

#!/bin/bash
while read line
do
perl_script <flags> $line  >> output_file
done < file_names.txt

我猜这种情况正在发生,因为-t STDIN返回false,因为它是非交互式运行的,所以它没有附加到终端。有没有办法确保在交互式运行脚本或从shell脚本调用脚本时我得到了正确的行为?

2 个答案:

答案 0 :(得分:0)

试试这个:

#!/bin/bash
TTY=`tty`
while read line
do
perl_script <flags> $line  < $TTY >> output_file
done < file_names.txt

答案 1 :(得分:0)

外部脚本将STDIN上的file_names.txt提供给循环,循环中的任何子进程都可以使用它。您的逻辑(就您的内部脚本而言)是正确的。但是,它有两种输入方式:命令行上的文件名和STDIN上file_names.txt文件的重定向,该文件提供给未连接到tty的循环。这是我对bash循环的主要抱怨之一。 STDIN重定向有点松散,循环内容会不经意间将其拾取。这就是为什么我喜欢tcsh的foreach:

#!/bin/tcsh
foreach line ( `cat file_names.txt` )
  perl_script <flags> $line  >> output_file
end

您也许也可以在bash中执行类似的操作,但是我不确定您的内部脚本是否会在STDIN上使用父脚本的句柄(因为我对bash相当陌生,并且一直在使用tcsh进行操作)几十年)。您可以尝试一下,看看是否可行:

for line in `cat file_names.txt`; do perl_script <flags> $line  >> output_file; done