【发布时间】:2015-08-06 09:51:40
【问题描述】:
我目前正在使用这两个 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 脚本调用,有没有办法确保我得到正确的行为?
【问题讨论】:
-
-t返回 true,即使您的脚本不在管道的读取端:perl -wE 'say "tty" if -t'。了解某些内容是否正在传递给 STDIN 的唯一方法是尝试从中读取。 -
@ThisSuitIsBlackNot 你能举个例子吗?
-
即
while (<>) { ... }。如果您不将文件名作为参数或管道数据传递给 STDIN,这将阻塞并等待输入,这正是 *nix 实用程序(例如cat、awk、wc)通常所做的。换句话说,我会删除您现在拥有的支票;您无法可靠地测试用户是否正在向 STDIN 输入内容(他们可能在您进行检查时正在输入内容),所以不要尝试。相反,做现有程序所做的事情:允许用户将文件名作为参数传递,通过管道输入数据,或通过提示手动输入。 -
我认为,如果
@ARGV != 0,你应该直接忽略stdin。 -
@ThisSuitIsBlackNot 谢谢。更新了我的脚本以像其他 *nix coreutils 一样工作,现在一切正常。
标签: linux bash perl shell stdin