我手头上有一些 Python 脚本,我正在努力重写它们。我和他们所有人都有同样的问题。
对我来说,如何编写程序以使它们表现得像正确的 UNIX 工具一样并不明显。
因为这
$ cat characters | progname
和这个
$ progname characters
应该产生相同的输出。
我能在 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
如果有 stdin,则 fileinput 库处理 stdin;如果有文件,则处理文件。但它迭代单行。
import fileinput
for line in fileinput.input():
process(line)
我真的不明白。我想如果您正在处理小文件,或者您没有对文件做太多操作,那么这可能看起来很明显。但是,就我的目的而言,这比简单地打开整个文件并将其读入字符串要慢得多,如上所述。
目前我运行上面的脚本就像
$ pythonscript textfilename1 > textfilename2
但我希望能够在管道中运行它(及其兄弟),例如
$ grep pattern textfile1 | pythonscript | pythonscript | pythonscript > textfile2
答案1
检查文件名是否作为参数给出,否则从中读取sys.stdin
.
像这样的东西:
if len(sys.argv) > 0:
f = open(sys.argv[1])
else:
f = sys.stdin
它与 Mikel 的答案类似,只是它使用了该sys
模块。我想,如果他们把它放在那里,那一定是有原因的……
答案2
为什么不只是
files = sys.argv[1:]
if not files:
files = ["/dev/stdin"]
for file in files:
f = open(file)
...
答案3
事实证明,我最喜欢的做法是......(这取自一个不错的 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()
我最喜欢这个的原因是,正如博主所说,如果不小心调用而没有输入,它只会输出一条愚蠢的消息。它也很好地融入了我现有的所有 Python 脚本中,因此我已经将它们全部修改以包含它。