Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 如何在perl脚本中检查管道数据_Linux_Bash_Perl_Shell_Stdin - Fatal编程技术网

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

Linux 如何在perl脚本中检查管道数据,linux,bash,perl,shell,stdin,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)); 当从shell以交互方式运行perl脚本时,

我目前正在使用这两个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));
当从shell以交互方式运行perl脚本时,这种方法可以很好地工作。例如,这些工作符合预期:

$ perl_script <flags> filename
$ cat | perl_script <flags>
$perl\u脚本文件名
$cat| perl_脚本
但是,当从bash脚本或类似于emacs中的org模式调用perl脚本时,该脚本会认为有数据正在通过管道传输,并在文件作为参数提供时抛出pod2usage错误。以下是导致此行为的示例:

#!/bin/bash
while read line
do
perl_script <flags> $line  >> output_file
done < file_names.txt
#/bin/bash
读行时
做
perl_脚本$line>>输出文件
完成
我猜这是因为
-t STDIN
返回false,因为它以非交互方式运行,所以没有连接到终端。如果脚本以交互方式运行或从shell脚本调用,是否有方法确保获得正确的行为

试试这个:

#!/bin/bash
TTY=`tty`
while read line
do
perl_script <flags> $line  < $TTY >> output_file
done < file_names.txt
#/bin/bash
TTY=`TTY`
读行时
做
perl_脚本$line<$TTY>>输出_文件
完成
外部脚本将STDIN上的文件_names.txt提供给循环,循环中的任何子进程都会获取该文件。您的逻辑(就您的内部脚本而言)是正确的。但是,它以两种方式获得输入:命令行上的文件名和STDIN上提供给未连接到tty的循环的文件_names.txt的重定向。这是我对bash中循环的主要抱怨之一。STDIN重定向是一种松散的规范,在不经意间被循环内容拾取。这就是为什么我喜欢tcsh的foreach:

#!/bin/tcsh
foreach line ( `cat file_names.txt` )
  perl_script <flags> $line  >> output_file
end
#/垃圾箱/垃圾箱
foreach行(`cat file\u names.txt`)
perl_脚本$line>>输出文件
结束
您也可以在bash中执行类似的操作,但我不确定您的内部脚本是否能够在STDIN上处理父脚本(因为我对bash相当陌生,已经使用tcsh几十年了)。您可以尝试一下,看看这是否有效:

for line in `cat file_names.txt`; do perl_script <flags> $line  >> output_file; done
用于“cat file_names.txt”中的行;执行perl_脚本$line>>输出_文件;完成

-t
即使脚本不在管道的读取端,也会返回true:
perl-如果-t'
,我们会说“tty”。知道是否有东西正在传递给STDIN的唯一方法是尝试从中读取。@ThisSuitesBlack您不能给出一个例子吗?例如,
while(){…}
。如果不将文件名作为参数或管道数据传递给STDIN,这将阻塞并等待输入,这正是*nix实用程序(例如,
cat
awk
wc
)通常所做的。换句话说,我会取消你现在的支票;您无法可靠地测试用户是否正在向STDIN输入内容(当您进行检查时,他们可能正在键入内容),因此不要尝试。相反,请执行现有程序所做的操作:允许用户将文件名作为参数传递、通过管道输入数据或通过提示符手动输入数据0
,您只需忽略
stdin
@thisSuiteisBlack不必谢。更新了我的脚本,使其与其他*nix coreutils一样工作,现在一切正常。