如何在不使用子进程命令
的情况下将以下内容转换为pythoncat $MYDIR/* |grep ABCD |grep zip |grep -v idx |awk -F'/' '{print $3}' |awk -F"_" '{print $2}' |awk -F"." '{print $1}' |sed 's/\$[A-Z]//g' | sort|uniq |egrep -v "^ABCD_G9" |egrep -v ABCD_00 |egrep -v "^ABCD_0[1-8]" > $DATADIR/ABCDDataFile
答案 0 :(得分:6)
您“分解”管道,了解每个部分的作用,然后在Python中重新编码每个部分,并根据需要进行连接。所以,让我们看看......:
cat $MYDIR/* |
此部分连接驻留在名称在环境变量MYDIR
中的目录中的所有文件。所以这可以实现,例如(在正确导入之后)
def p1():
filenames = glob.glob(os.environ['MYDIR'] +'/*')
for filename in filenames:
with open(filename) as f:
for line in f:
yield line
使用生成器来模拟shell管道的缓冲同时性。
grep ABCD |
此部分接受行,仅发出包含'ABCD'的行。例如,
def grep(pattern, inseq):
for line in inseq:
if pattern in line: yield line
和
类似grep zip |
下一部分,
grep -v idx |
只需要反转grep
,所以:
def grepv(pattern, inseq):
for line in inseq:
if pattern not in line: yield line
等等。翻译egrep
和sed
需要正则表达式,但在其他方面非常相似,所以我会把这些内容留给你;此处使用的awk
只需要各种“字段分隔符”.split
以及结果列表的索引。
sort | uniq |
实际上最好翻译成单件:
def sortuniq(inseq):
for line in sorted(set(inseq)): yield line
(使用发生器与以前的情况保持一致)。
所以,一旦你翻译了每一篇文章,你就可以按照自己喜欢的方式连接它们。
连接的简单方法是通过函数调用,但这需要一些不自然的顺序,即最左边的部分(“source”,p1
)成为深层嵌套调用的最内层参数。通过在交互式翻译提示符下进行import this
,我们从其他智慧的角度中学习“扁平比嵌套更好”。
有点花哨(使用functools.partial
在需要的地方预先绑定前导args,因此只留下只需要inseq
作为参数的过滤器函数)可以走得很远......:
def pipeline(source, *filters):
curf = source
for f in reversed(filters):
curf = functools.partial(f, curf())
for line in curf():
yield line
并将结果写入某个文件,
with open(whatever, 'v') as f:
f.writelines(
pipeline(
p1,
functools.partial(grep, 'ABCD'),
functools.partial(grep, 'zip'),
# etc, etc
我真的会以这种方式编码吗?很可能不会 - 我会对整个管道试图做的事情进行反向工程,而不是一步一步地将它们全部连接起来。虽然Python是一种灵活的多范式语言,但使用它来严格模拟shell典型的管道方法不在操作上是最优的。但是,它可能非常有启发性,这就是为什么我花了一些时间在这里展示它!