sed を使用した Bash while ループの検索と置換

sed を使用した Bash while ループの検索と置換

次のスクリプトに問題があります (これが関連する部分です)。

#!/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変数を使用すると、ループ内で正しい文字列が取得されます。コマンドで明示的に 2 つの文字列が設定されている場合は、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++))無限ループを防ぐために追加されました(クサラナンダのコメント)。

関連情報