将 bash 脚本转换为 python 不带子进程
convert bash script to python without subprocess
如何在不使用子进程命令的情况下将以下内容转换为 python
cat $MYDIR/* |grep ABCD |grep zip |grep -v idx |awk -F'/' '{print }' |awk -F"_" '{print }' |awk -F"." '{print }' |sed 's/$[A-Z]//g' | sort|uniq |egrep -v "^ABCD_G9" |egrep -v ABCD_00 |egrep -v "^ABCD_0[1-8]" > $DATADIR/ABCDDataFile
你 "decompose" 管道,了解每个部分的作用,然后在 Python 中重新编码每个部分,适当连接。那么,让我们看看...:[=31=]
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
只需要各种 "field separators" 的 .split
和结果列表的索引。
sort | uniq |
其实最好翻译成一篇:
def sortuniq(inseq):
for line in sorted(set(inseq)): yield line
(使用生成器与前面的案例保持一致)。
所以,一旦你翻译了每一个片段,你就可以用你喜欢的任何方式连接它们。
连接的简单方法是通过函数调用,但这需要某种不自然的顺序,即最左边的部分("source"、p1
)成为深层嵌套调用的最内层参数。通过在交互式解释器提示符下执行 import this
,我们了解到 "flat is better than nested".
有点花哨(使用 functools.partial
在需要的地方预先绑定前导参数,从而只留下只接受 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 典型的管道方法在操作上 不是 最佳。然而,它可能很有启发性,这就是为什么我在这里花了一些篇幅来展示它!
如何在不使用子进程命令的情况下将以下内容转换为 python
cat $MYDIR/* |grep ABCD |grep zip |grep -v idx |awk -F'/' '{print }' |awk -F"_" '{print }' |awk -F"." '{print }' |sed 's/$[A-Z]//g' | sort|uniq |egrep -v "^ABCD_G9" |egrep -v ABCD_00 |egrep -v "^ABCD_0[1-8]" > $DATADIR/ABCDDataFile
你 "decompose" 管道,了解每个部分的作用,然后在 Python 中重新编码每个部分,适当连接。那么,让我们看看...:[=31=]
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
只需要各种 "field separators" 的 .split
和结果列表的索引。
sort | uniq |
其实最好翻译成一篇:
def sortuniq(inseq):
for line in sorted(set(inseq)): yield line
(使用生成器与前面的案例保持一致)。
所以,一旦你翻译了每一个片段,你就可以用你喜欢的任何方式连接它们。
连接的简单方法是通过函数调用,但这需要某种不自然的顺序,即最左边的部分("source"、p1
)成为深层嵌套调用的最内层参数。通过在交互式解释器提示符下执行 import this
,我们了解到 "flat is better than nested".
有点花哨(使用 functools.partial
在需要的地方预先绑定前导参数,从而只留下只接受 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 典型的管道方法在操作上 不是 最佳。然而,它可能很有启发性,这就是为什么我在这里花了一些篇幅来展示它!