ixt*_*lix 29 pipe python text-processing stdout stdin
我有一些 Python 脚本,我正在努力重写它们。我对他们都有同样的问题。
我不清楚如何编写程序以使它们表现得像适当的 unix 工具。
因为这
$ cat characters | progname
Run Code Online (Sandbox Code Playgroud)
和这个
$ progname characters
Run Code Online (Sandbox Code Playgroud)
应该产生相同的输出。
我能在 Python 中找到的最接近的东西是 fileinput 库。不幸的是,我真的不知道如何重写我的 Python 脚本,所有这些脚本都是这样的:
#!/usr/bin/env python
# coding=UTF-8
import sys, re
for file in sys.argv[1:]:
f = open(file)
fs = f.read()
regexnl = re.compile('[^\s\w.,?!:;-]')
rstuff = regexnl.sub('', fs)
f.close()
print rstuff
Run Code Online (Sandbox Code Playgroud)
fileinput 库在有标准输入时处理标准输入,如果有文件则处理文件。但它迭代单行。
import fileinput
for line in fileinput.input():
process(line)
Run Code Online (Sandbox Code Playgroud)
我真的不明白。我想如果您正在处理小文件,或者您对文件没有做太多事情,这似乎很明显。但是,就我而言,这比简单地打开整个文件并将其读入字符串要慢得多,如上所述。
目前我运行上面的脚本
$ pythonscript textfilename1 > textfilename2
Run Code Online (Sandbox Code Playgroud)
但我希望能够在管道中运行它(及其兄弟),比如
$ grep pattern textfile1 | pythonscript | pythonscript | pythonscript > textfile2
Run Code Online (Sandbox Code Playgroud)
rah*_*hmu 15
检查文件名是否作为参数给出,否则从sys.stdin.
像这样的东西:
if sys.argv[1]:
f = open(sys.argv[1])
else:
f = sys.stdin
Run Code Online (Sandbox Code Playgroud)
它类似于 Mikel 的答案,只是它使用了sys模块。我想如果他们把它放在那里,那一定是有原因的......
Mik*_*kel 10
为什么不只是
files = sys.argv[1:]
if not files:
files = ["/dev/stdin"]
for file in files:
f = open(file)
...
Run Code Online (Sandbox Code Playgroud)
事实证明,我更喜欢的做法是......(这是从一个名为Harbinger's Hollow的不错的 Linux 小博客中获取的)
#!/usr/bin/env python
import argparse, sys
parser = argparse.ArgumentParser()
parser.add_argument('filename', nargs='?')
args = parser.parse_args()
if args.filename:
string = open(args.filename).read()
elif not sys.stdin.isatty():
string = sys.stdin.read()
else:
parser.print_help()
Run Code Online (Sandbox Code Playgroud)
我最喜欢这个的原因是,正如博主所说,如果在没有输入的情况下意外调用,它只会输出一条愚蠢的消息。它也很好地插入了我所有现有的 Python 脚本中,我已经修改了它们以包含它。