Bash while 循環搜尋並使用 sed 替換

Bash while 循環搜尋並使用 sed 替換

我的以下腳本有問題(這是它的相關部分):

#!/bin/bash

OLD=(
"_MAIN1_"
"_MAIN2_"
)

NEW=(
"#111"
"#222"
)

length=${#OLD[*]}

i=0

while (( i < length ))
do
  sed -e "s/${OLD[$i]}/${NEW[$i]}/g" oldfile.txt > newfile.txt

  #sed -e 's/_MAIN1_/#111/g' oldfile.txt > newfile.txt  # this works

  # Another way that does not work
  #sed -e 's/'"${OLD[$i]}"'/'"${NEW[$i]}"'/g' oldfile.txt > newfile.txt

  ((i++))
done

exit 0

我的目標是替換文件中的字串並將其保存到新文件中。 「舊」和「新」字串儲存在陣列中。

我嘗試了很多方法並使用單引號和雙引號 - 但沒有任何效果。當我echo輸入變數時,我在循環內得到了正確的字串。如果在命令中明確設定了兩個字串,則sed它可以正常工作。

字串模式遵循我的範例陣列中的模式(“new”包含下劃線“_”,“old”包含主題標籤“#”)。

我在 Ubuntu 16.04 機器上運行 bash。

非常感謝!

答案1

建立一個sed執行所有替換的腳本,然後將該sed腳本套用到您的檔案。

for (( i=0; i<${#OLD[@]}; ++i )); do
        printf 's/%s/%s/g\n' "${OLD[$i]}" "${NEW[$i]}"
done >script.sed

sed -f script.sed inputfile >outputfile && mv outptufile inputfile && rm script.sed

透過這種方式,您可以將需要解析輸入檔案的次數限制為一次。

對於給定的數據OLDNEW腳本sed將生成為

s/_MAIN1_/#111/g
s/_MAIN2_/#222/g

答案2

您的整個腳本(不起作用)可以用一行替換:

sed 's/_MAIN\([12]\)_/#\1\1\1/g' oldfile.txt > newfile.txt

或者,更易讀但等效:

sed 's/_MAIN1_/#111/g;s/_MAIN2_/#222/g' oldfile.txt > newfile.txt

還有幾十種其他方法可以實現此目的,具體取決於您的情況實際的用例(例如,資料來自哪裡、值的實際情況、您嘗試對資料執行什麼操作等)。

答案3

謝謝拉克什·夏爾馬的評論我可以透過使用-ised 命令中的標誌來解決這個問題。在循環之前備份原始檔案:

cp oldfile.txt oldfile.backup
while (( i < length ))
do
  sed -i -e 's/'"${OLD[$i]}"'/'"${NEW[$i]}"'/g' oldfile.txt
  ((i++))
done

下次我將使用 Perl 進行字串操作。

編輯:添加((i++))以防止無限循環(感謝善行難陀的評論)。

相關內容