如何在bash中使Python脚本“可管道”?
问题的原因是脚本中的循环方式不正确,而且不符合Pythonic的编程风格。实际上,空的输入行会打破循环。一个简单且标准的解决方法是使用for line in sys.stdin
来读取标准输入。此外,初始的line = ''
是完全多余的。
解决方法是将循环方式改为使用for line in sys.stdin
,并且删除掉初始的line = ''
。此外,还可以按照PEP 8标准,将代码的缩进改为4个空格。
下面是修改后的代码:
import sys if __name__ == "__main__": for line in sys.stdin: sys.stderr.write("DEBUG: got line: " + line) sys.stdout.write(line)
通过这种修改,脚本就能够在bash中以管道方式使用了。比如,可以使用以下命令:
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
这样就实现了将Python脚本与bash的管道操作结合起来的目的。
如何使python脚本在bash中可以通过管道传递数据?
在bash中,可以使用管道将一个命令的输出作为另一个命令的输入。然而,有时候我们希望能够将一个python脚本作为一个可用的命令来接受管道中的数据。这样就可以像使用其他UNIX工具一样使用python脚本了。
要实现这一点,我们可以使用python的fileinput模块。该模块允许我们在脚本中实现UNIX工具的典型行为:
1)如果没有指定参数,从stdin中读取数据;
2)可以指定多个文件作为参数;
3)单个参数“-”表示stdin。
下面是一个使用fileinput模块的grep示例代码:
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:]))
在上述例子中,我们定义了一个grep函数,它接受一个包含输入行的迭代器和一个正则表达式对象,然后返回一个生成器,用于筛选出匹配正则表达式的行。
在main函数中,我们首先检查是否提供了足够的参数,如果没有,则打印错误消息并返回退出码2。然后,我们使用re.compile函数将第一个参数(正则表达式模式)编译为正则表达式对象。接下来,我们使用fileinput.input函数获取用于读取输入的迭代器。最后,我们遍历输入行并使用sys.stdout.write函数将匹配的行写入到stdout。
要将python脚本作为可用的命令来接受管道中的数据,可以像这样调用脚本:
$ seq 1 20 | python grep.py "4" 4 14
在上述例子中,我们使用seq命令生成1到20的数字序列,并将其通过管道传递给grep.py脚本。脚本会将所有包含数字4的行输出到stdout。
通过使用fileinput模块和特定的命令行参数处理逻辑,我们可以很方便地使python脚本能够像其他UNIX工具一样接受管道传递的数据。这使得我们可以更灵活地使用python来处理和转换数据。
如何在bash中使python脚本可“pipeable”?
问题出现的原因:
在Python脚本中,你只需要从标准输入(stdin)读取数据。
解决方法:
为了使Python脚本可在bash中使用管道(pipe)操作,可以使用以下方法:
1. 使用sys模块中的stdin对象来读取标准输入。可以通过以下代码实现:
import sys for line in sys.stdin: # 处理每行数据 print(line)
2. 使用fileinput模块来处理输入。fileinput模块可从标准输入或文件中一次读取一行数据。可以通过以下代码实现:
import fileinput for line in fileinput.input(): # 处理每行数据 print(line)
3. 使用click库来处理命令行参数和输入。click库提供了一个方便的方法来处理命令行输入。可以通过以下代码实现:
import click @click.command() def process_input(): for line in click.open_file('-', stdin=True): # 处理每行数据 click.echo(line) if __name__ == '__main__': process_input()
通过这些方法,可以使Python脚本可在bash中使用管道操作,从而实现更灵活的数据处理。