【问题标题】:Read stdin from inlined python in bash从 bash 中的内联 python 读取标准输入
【发布时间】:2014-12-04 18:35:56
【问题描述】:

谁能解释一下为什么这个简短的 bash / python 命令不输出“hello”

$ echo hello | python - <<END
import sys
for line in sys.stdin:
  print line
END

如果我将我的 python 脚本保存到文件中,此命令将按预期工作。

在 script.py 中

import sys
for line in sys.stdin:
  print line
END

$ echo "你好" | python脚本.py

“你好”

【问题讨论】:

    标签: python bash


    【解决方案1】:

    它不起作用的原因是您有冲突的重定向。 echo | python 尝试将标准输入绑定到来自echo 的管道,而python - &lt;&lt;HERE 尝试将标准输入绑定到此处的文档。你不能两者兼得。 (此处的文档获胜。)

    但是,实际上没有理由要在标准输入上通过管道传输脚本本身。

    bash$ echo hello | python -c '
    > import sys
    > for line in sys.stdin:
    >   print line'
    hello
    

    【讨论】:

      【解决方案2】:

      因为python &lt;&lt; END 重定向标准输入以读取程序。您也无法在标准输入上读取来自echo 的行。

      【讨论】:

        【解决方案3】:

        哦,男孩,这是有道理的!过去一个小时我一直在努力解决这个问题,终于明白了,谢谢你们。

        要为原始程序提供可行的替代方案,您可以执行以下操作:

        $ echo hello | python <(cat <<END
        import sys
        for line in sys.stdin:
          print line
        END
        )
        

        但要小心!如果你把它放在一个文件中,最后的END 需要接触左边的排水沟(没有空格)。否则,它不会解析“查找匹配字符时文件意外结束”错误或类似的错误(实际上,从我开始回答这个问题开始,我又花了两个小时才弄清楚)。

        解释代码,发生的事情是&lt;&lt;END ... END&lt;(cat ...) 结合创建一个文件(在/dev/fd 中),以便可以将其提供给python,就好像它是一个真实文件一样。引用this关于&lt;(...)的解释:

        这是进程替换。它将命令的输出输入到 可以像普通文件一样读取的 FIFO。

        关于这个话题还有另一个有趣的答案here

        【讨论】:

        • 这是一个创新但从根本上来说仍然是useless use of cat。 shell 不需要cat 在进程替换中的帮助来将 here 文档提供给 Python,尽管该结构避免了标准输入(shell 基本上使进程替换的输出可用作命名的临时文件) .