如何在bash中使Python脚本“可管道化”?

64

我写了一个脚本,希望在bash中可以通过管道使用它。类似于:

echo "1stArg" | myscript.py

有可能吗?怎么做?


你会如何在bash中完成同样的事情? - Cadoiz
4个回答

81

看看这个简单的echo.py

import sys

if __name__ == "__main__":
    for line in sys.stdin:
        sys.stderr.write("DEBUG: got line: " + line)
        sys.stdout.write(line)

运行:

ls | python echo.py 2>debug_output.txt | sort

输出:

echo.py
test.py
test.sh

debug_output.txt的内容:

DEBUG: got line: echo.py
DEBUG: got line: test.py
DEBUG: got line: test.sh

5
while True这种循环写法既不正确也不符合Python风格。实际上,输入空行会打破循环。一个简单而标准的解决方案是使用for line in sys.stdin来读取标准输入。此外,初始的line = ''完全是多余的。 - Eric O. Lebigot
2
太好了!我已经为您的代码进行了缩进,使用标准的4个空格 (参见PEP 8),而不是原来您使用的2个空格。 - Eric O. Lebigot

21

我将补充其他答案,提供一个使用 grep 的示例,它使用fileinput实现了UNIX工具的典型行为:1)如果没有指定参数,则从标准输入读取数据;2)可以指定多个文件作为参数;3)单个参数-表示标准输入。

import fileinput
import re
import sys

def grep(lines, regexp):
    return (line for line in lines if regexp.search(line))

def main(args):
    if len(args) < 1:
        print("Usage: grep.py PATTERN [FILE...]", file=sys.stderr)
        return 2 

    regexp = re.compile(args[0])
    input_lines = fileinput.input(args[1:])

    for output_line in grep(input_lines, regexp):
        sys.stdout.write(output_line)

if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))

例子:

$ seq 1 20 | python grep.py "4"
4
14

11

5

任何从标准输入读取的内容都可以进行“管道化”处理。管道操作只是将前一个程序的标准输出重定向到后一个程序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接