将bash循环迭代输出到下一个迭代中

问题描述:

我有一个替换列表,我想用sed执行。而不是将替换组合成单个sed命令,我想在bash循环的迭代中执行每个替换。例如:将bash循环迭代输出到下一个迭代中

cat ${input} | 
for subst in "${substlist}"; do 
    sed 's/'${subst}'/modified_'${subst}'/g' 
done > ${output} 

我希望每次迭代修改整个流,但我只看到第一次迭代获取输入。

这个模式可能在bash中吗?

+0

顺便说一句,'$ {substlist}'正在扩大一个字符串 - 通常说起来,你应该使用一个合适的数组,而不是通过未引用的扩展来依赖分词。也就是说,最好的做法是'substlist =(“first”“second”“third”);对于“$ {substlist [@]}”中的subst; do ...' –

+1

你为什么不想把它们组合成一个'sed'命令?这就是几个答案。 – Barmar

+0

顺便说一句,如果你想在不同的'sed'进程中(不管什么奇怪的原因)同时运行所有的替换(即,并发),那种最适用于此的“循环”是一个递归函数vs bash '为'循环。例如:'multised(){case $#in 0)cat ;; 1)sed -e“$ 1”;; *)当地cur = $ 1;转移; sed -e“$ cur”|多重“$ @”;; ESAC; }' - 可用作'multised'$ {substs [@]}“”$ output“'如果你有一个'substs'在一个数组中。 –

将输入文件复制到输出文件,然后使用-i选项执行sed替换以保持覆盖该文件。

cp "$input" "$output" 
for subst in $substlist 
do 
    sed -i "s/$subst/modified_$subst/g" "$output" 
done 

随着BSD/OSX sed需要是:

sed -i '' "s/$subst/modified_$subst/g" "$output" 
+0

额外的复制操作,并采取可移植性命中(不会与BSD'sed'版本的'-i'),为什么? –

+0

@CharlesDuffy他们说他们不想在一个'sed'命令中完成它。 – Barmar

+0

啊。我会......有兴趣......知道是否有真正的原因(相对于XY问题 - 即不知道可以用循环构建参数列表),而是公平的“nuff”。 –

这里是做作为单个流的一种方式。从${substlist}建立战略经济对话的参数和调用SED一次:

#!/bin/sh 

cat ${input} | 
sed `for subst in ${substlist}; do 
     echo " -e s/${subst}/modified_${subst}/g " 
    done` > ${output} 

根据什么是${substlist},你可能需要做更多的逃逸。

+0

已经足够糟糕了,OP已经运行了一次没有引号的扩展。做*的输出的未引用扩展*会增加更多失败案例的用途。 (另外,由于bash的'echo'不符合POSIX规范,这里的'-e'修改了它的行为方式,而不是让'sed'传递一个字面的'-e'参数,其最终结果是除了一个替换之外的所有替换都将被视为输入文件名,而不是由'sed'执行的操作)。 –

+0

优秀点。 –

+0

@CharlesDuffy编辑表示#!/ bin/sh但同意echo的可移植性问题使它成为一个糟糕的解决方案。 –

创建一个-e选项的数组传递给sed

filters=() 
for subst in ${substlist}; do 
    filters+=(-e "s/$subst/modified_$subst/") 
done 
sed "${filters[@]}" "$input" > "$output" 

(遍历一个没有引号的参数扩展和动态地创建每个sed滤波器的问题超出这个答案的范围)