2017-10-17 118 views
0

我有一個替換列表,我想用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 [@]}「<"$input" >」$ output「'如果你有一個'substs'在一個數組中。 –

回答

-1

將輸入文件複製到輸出文件,然後使用-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」。 –

0

這裏是做作爲單個流的一種方式。從${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的可移植性問題使它成爲一個糟糕的解決方案。 –

1

創建一個-e選項的數組傳遞給sed

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

(遍歷一個沒有引號的參數擴展和動態地創建每個sed濾波器的問題超出這個答案的範圍)