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

これにより、入力ファイルを解析するのに必要な回数を1回に制限できます。

与えられたデータに対して、スクリプトは次OLDNEWようsedに生成されます。

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

答え2

機能しないスクリプト全体を1行に置き換えることができます。

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++))無限ループ防止のため追加されました(ありがとうございます先行は達成するのが難しい)のコメント。

関連情報