我不确定是否以前询问过这一点,但是我想知道如何实现python中的"定向"的语法来模仿unix shell Pipelines。特别是,如何使用可以产生,修改或消耗记录流的"普通python函数",并且可以使用"。操作员。
一个直接的示例,假设python函数与unix程序一样:
在UNIX中,我们可以做:
ls | egrep '^a' | wc -l
计算以" A"开头的当前目录中的文件。怎么样:
from unixtools import *
ls().egrep('^a').wc(countLines=True)
和LS的实现可能就像是生成器:
@pipeline
def ls():
for file in glob.glob("*"):
yield file
我已经省略了明显的胶水代码,这将使将 ls 与管道的其他"命令"连接起来。
@pipeline 是尝试使用装饰器将普通python函数转换为管道协议的成员。
我意识到这可以使用Python的传统语法完成,这是不太可读的迫使您反向写入的,而更多的错误容易容易出现:
wc(countLines=True,input=egrep("^a",input=ls()))
我想我们可以研究Python Pyquery 的实现。
显然,python管套件非常接近我的要求,我不知道。
所以,我正在回答自己的问题,因为管道包装文档对我所陈述的问题不是很直观。特别是在实施完整的Unix Shell Pipe语义时。最后,关于一些常见的Unix技巧还有更多未解决的问题。
我们可以使用@pipe Decorator创建生产者作为Python发电机。请注意,这种类型的生产者只能是管道的第一个成员:
from pipe import Pipe
@Pipe
def producer(arg=10):
for x in range(arg):
yield x
就像在Unix中一样,您可以定义一个变压器,该变压器有望改变其输入并生成输出:
@Pipe
def transformer(iterable, arg=2):
for x in iterable:
if x % arg == 0: yield x*2
我们可以使用"管道"语法连接生产商和变压器,该语法类似于Unix Shell Pipeline的语法:
producer() | transformer()
与unix shell不同,这不会产生输出;-(您可以写一个消费者,该消费者会消耗其输入并打印一些东西:
@Pipe
def consumer(iterable):
for x in iterable:
print(x)
现在,连接将按预期工作:
producer() | transformer() | consumer()
有趣的是,在第二或多个管道元素上,我们可以省略括号,只使用管道函数的名称:
producer(10) | transformer | consumer
我喜欢的另一个功能是shell的"这里文档":
[1,2,3,4] | transformer | consumer
在这种情况下,[1,2,3,4]被解释为可能产生的一个值的序列,并且在管道中的下一个元素中"管道"。
。,我们当然可以收集管道结果:
a = [1,2,3,4] | transformer | consumer
现在最后在某些情况下,如何处理"管道"并不是很明显:
尚不清楚如何在外壳中进行等效的stdout合并:
(echo today ; date) | wc
也许使用" CAT"生产商,能够加入其所有峰值输入?
cat(echo("today"),date()) | ...
尚不清楚如何仅消耗管道的几个元素,然后继续使用另一个功能,例如在unix shell中:
cat /etc/passwd | (read line ; cat)
在这种情况下,阅读会消耗第一行,而猫会看到其余的。我们可以超载"("one_answers")"符号?