Bash 如何在命令之间重复管道输入,直到应用输出条件?
我想创建一个bash脚本,该脚本在两个进程之间重复管道输出,直到输出包含一些特殊字符 考虑以下两个Python脚本: script1.pyBash 如何在命令之间重复管道输入,直到应用输出条件?,bash,shell,Bash,Shell,我想创建一个bash脚本,该脚本在两个进程之间重复管道输出,直到输出包含一些特殊字符 考虑以下两个Python脚本: script1.py from sys import stdin for line in stdin.readline(): if line.isdigit(): print int(line) + 3 from sys import stdin for line in stdin.readline(): if line.isdigit():
from sys import stdin
for line in stdin.readline():
if line.isdigit():
print int(line) + 3
from sys import stdin
for line in stdin.readline():
if line.isdigit():
print int(line) - 1
script2.py
from sys import stdin
for line in stdin.readline():
if line.isdigit():
print int(line) + 3
from sys import stdin
for line in stdin.readline():
if line.isdigit():
print int(line) - 1
以及下面的执行
$ echo 0|python script1.py|python script2.py|python script1.py|python script2.py
4
是否可以创建一个Bash脚本,执行这两个脚本并将输出作为输入传递给另一个脚本,直到script1的输出达到某个特定数量
(我不想修改Python脚本,我不是在实际使用它们,它们只是为了演示我想要实现的目标而创建的)。假设您的Python脚本
script2.py
在一行上只输出一个数字,您希望执行pythonscript1.py | pythonscript2.py
,直到输出编号为4
,下面是一种递归方法。它使用递归,因此如果调用过多,您可能会遇到堆栈溢出:
#!/bin/bash
apply_until4() {
local l
read l < <(python script1.py | python script2.py)
if [[ $l = 4 ]]; then
echo "$l"
return
fi
echo "$l" | apply_until4
}
echo "0" | apply_until4
没有递归的另一种可能性:
#!/bin/bash
apply_until4() {
local l
read l
until [[ $l = 4 ]]; do
read l < <(echo "$l" | python script1.py | python script2.py)
done
echo "$l"
}
echo "0" | apply_until4
语句可以更改为
l=$(python script.py | python script2.py)
l=$(echo "$l" | python script1.py | python script2.py)
同样地
read l < <(echo "$l" | python script1.py | python script2.py)
不同的是,读取
将丢弃所有前导空格和尾随空格(如果有)
- 一种可以防止叉式炸弹的更安全方法:
function piper {
read
if [[ $REPLY == 4 ]]; then
echo 4
elif [[ $REPLY =~ ^[[:digit:]]+$ && $REPLY -lt 4 ]]; then
echo "$REPLY" | python script1.py | python script2.py | piper
fi
}
echo 0 | piper
您想要一个双向管道吗?在概念上与我的递归答案没有区别(并且会有相同的缺陷wrt stackoverflows)。你说的更安全是什么意思?是否只是因为您检查组合的输出是由数字组成的单词?还是我错过了什么?我的答案是什么,会制造一个叉子炸弹?(潜在无限循环,是的,叉形炸弹,我没有看到任何)。此外,正则表达式可能是过度杀伤力,一个glob就可以了;你的测试不是错误就是没用。@gniourf\u gniourf我发现
[[$REPLY-lt 4]]]
有点效率低下,但我懒得计算它。你能证明为什么它没用吗?关于叉形炸弹,echo“$l”| apply__|4
可以产生无限的次壳层。为什么正则表达式会被过度使用?什么样的精确表达才足够呢?哦,是的,通过更仔细的检查,$REPLY=[:digit:]
似乎就足够了,因为目标不会增加。echo“$l”| apply|直到4
可以产生无限的子shell,当OP给出的玩具脚本的初始条件错误时,我的回答的目的是展示可以用来实现OP所达到的目标的概念,而不是围绕一个明显的演示案例来设计一个100%的防弹脚本。话虽如此,我们讨论的其他问题变得无关紧要。不过,有两件事:[$REPLY=+([[:digit:]])]
来避免正则表达式;这个安全防护装置使我无法用负数初始化:[$REPLY=?(-)+([[:digit:]])]]
这就是我这么做的明显原因。为了避免可能的分叉炸弹,以防OP错误地发送错误的初始输入。如果要检查glob模式,还需要=
而不仅仅是=
。由于还使用扩展模式,因此需要初始化extglob
。我总是喜欢ext.glob,并对它进行了第一次模式检查,但我只是选择使用正则表达式来减少行数并防止多余的shopt调用。