【问题标题】:piping from stdin to a python code in a bash script从标准输入到 bash 脚本中的 python 代码的管道
【发布时间】:2014-03-25 08:42:50
【问题描述】:

我有一个包含 python 代码的 bash 脚本 f。该 python 代码从标准输入中读取。我希望能够按如下方式调用我的 bash 脚本:

f input.txt > output.txt

在上面的示例中,python 代码将从 input.txt 读取并写入 output.txt。

我不知道该怎么做。我知道如果我只想写入一个文件,那么我的 bash 脚本应该是这样的

#!/bin/bash
python << EOPYTHON > output.txt
#python code goes here
EOPYTHON

我尝试将上面代码中的第二行更改为以下内容,但没有运气

python << EOPYTHON $*

我不知道该怎么做。有什么建议吗?

编辑 我将举一个更具体的例子。考虑以下 bash 脚本,f

#!/bin/bash
python << EOPYTHON 
import sys
import fileinput
for i in fileinput.input():
    sys.stdout.write(i + '\n')
EOPYTHON

我想使用以下命令运行我的代码

f input.txt > output.txt

如何更改我的 bash 脚本,使其使用“input.txt”作为输入流?

【问题讨论】:

  • f &lt; input.txt &gt; output.txt 有什么问题?
  • "我有一个包含 python 代码的 bash 脚本 f。" 为什么?如果您坚持每个源文件使用一种语言,您可能会发现代码更易于维护。
  • 所以我将问题解释为您想知道将 python 输出直接重定向到脚本中的何处(即脚本被称为将 stoudt 重定向到 output.txt)。我的回答应该可以解决这个问题,但仍然有点好奇为什么不能只将 python 打印到标准输出并让 bash 处理来自脚本外部的重定向?
  • @Johnsyweb 你从来没有为用另一种语言编写的脚本制作过包装器?
  • @BroSlow:当然有,但是包装器可以调用外部文件而不是包含它。这种关注点分离提高了可测试性和可维护性。

标签: python bash


【解决方案1】:

由于没有人提到这一点,这是作者要求的。神奇的是将“-”作为参数传递给 cpython(从标准输入读取源代码的指令):

输出到文件:

python - << EOF > out.txt
print("hello")
EOF

执行示例:

# python - << EOF
> print("hello")
> EOF
hello

由于数据不能再通过标准输入传递,这里还有一个技巧:

data=`cat input.txt`

python - <<EOF

data="""${data}"""
print(data)

EOF

【讨论】:

  • 为什么需要- 参数?在我看来python &lt;&lt; EOF ... EOF 也可以,除非您需要将参数传递给...
  • @BigMcLargeHuge 检查您的python --help 命令。在某些发行版中,它是默认参数,在某些发行版中不是。省略它只是在受支持的版本或二进制文件上默认使用它,而明确使用它可以保证结果。
  • 这似乎比 -c 更重要
【解决方案2】:

更新答案

如果您绝对必须按照您要求的方式运行,您可以这样做:

#!/bin/bash
python -c 'import os
for i in range(3):
   for j in range(3):
     print(i + j)
'  < "$1"

原答案

将您的 python 代码保存在一个名为 script.py 的文件中,并将您的脚本 f 更改为:

#!/bin/bash
python script.py < "$1"

【讨论】:

  • 我想要一个解决方案,而不在我的目录中保存另一个文件
  • 请再看一下 - 我已经更新为在被单引号包围时使用 Bash 的多行输入。
  • +1;将-c 与Python 源代码字符串一起使用确实是关键:它允许将stdin 输入传递给Python 代码(而不是像&lt;&lt;EOPYTHON 语法那样将stdin 输入解释为Python 代码);它还允许将参数传递给 Python 代码,后者可以使用sys.argv[1],...(在import sys 之后)访问。
【解决方案3】:

您可以根据进程的文件描述符列表检查它,即在 proc 文件系统上,您可以使用

打印 stdout 的重定向位置
readlink /proc/$$/fd/1

例如

> cat test.sh
#!/bin/bash
readlink /proc/$$/fd/1
> ./test.sh
/dev/pts/3
> ./test.sh > out.txt
> cat out.txt 
/home/out.txt

【讨论】:

    【解决方案4】:

    @Mark Setchell's answer 中的-c 选项应该可以工作。

    这是您在 Python 脚本中嵌入 bash 的替代方法:

    #!/usr/bin/env python
    import sys
    import fileinput
    from subprocess import call
    
    # shell command before the python code
    rc = call(r"""
    some bash-specific commands here
    ...
    """, shell=True, executable='/bin/bash')
    
    for line in fileinput.input():
        sys.stdout.write(line) #NOTE: `line` already has a newline
    
    # shell command after the python code
    rc = call(r"""
    some /bin/sh commands here
    ...
    """, shell=True)
    

    【讨论】:

      【解决方案5】:

      使用进程替换来传递 python 代码。这释放了可以照常使用的常规 io 间接寻址。

      ❯ seq 1 5 > input.txt
      ❯ python3 <input.txt <(<< EOS
      import sys
      print("Running script with args: ", sys.argv)
      for line in sys.stdin:
        print("line is %s" % line, end='')
      EOS
      )
      Running script with args:  ['/proc/self/fd/11']
      line is 1
      line is 2
      line is 3
      line is 4
      line is 5
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-04-15
        • 2013-06-10
        • 2016-03-01
        • 1970-01-01
        • 2011-04-29
        • 2011-03-12
        • 2016-05-30
        相关资源
        最近更新 更多