web-dev-qa-db-ja.com

ループ検索中のbash、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コマンドで2つの文字列が明示的に設定されている場合、これは問題なく機能します。

文字列パターンは、私の例の配列のパターンに従います(「new」にはアンダースコア「_」が含まれ、「old」にはハッシュタグ「#」が含まれます)。

Ubuntu 16.04ボックスでbashを実行しています。

どうもありがとうございました!

2
mazienho

すべての置換を行う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つに制限します。

OLDおよびNEWの指定されたデータに対して、sedスクリプトは次のように生成されます

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

スクリプト全体(機能しない)は、次の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

actualの使用例(たとえば、データの取得元、値が実際にどのように見えるか、データに対して何をしようとしているのかなど)に応じて、これを実現する方法は他にも数十あります。 。)。

0
Wildcard