単語をますます多くの数に置き換える方法は?

単語をますます多くの数に置き換える方法は?

たとえば、file.txtの唯一のコンテンツは次のとおりです。

xxxxxxxxxHAHAxxxxxxHOHOxxxxxxx  

HAHAをseq 1 3に変更し、HOHOをseq 5 7に変更したいので、出力は次のようになります。

xxxxxxxxx1xxxxxx5xxxxxxx   
xxxxxxxxx2xxxxxx6xxxxxxx   
xxxxxxxxx3xxxxxx7xxxxxxx   

私がしたこと:

for i in $(seq 1 3)    
do  sed "s/HAHA/$i/g" file.txt   
  for i in $(seq 5 7)    
  do sed "s/HOHO/$i/g" file.txt   
  done   
done > new.txt     

しかし、new.txtは私が期待したものを表示しません。コードをどのように変更する必要がありますか?

答え1

bash組み込みコマンドを使用してreadさまざまなファイル記述子の機能を読み取る方法は次のとおりです。

while read -u3 i && read -u4 j; do 
    sed -e "s/HAHA/$i/" -e "s/HOHO/$j/" file.txt
done > new.txt 3< <(seq 1 3) 4< <(seq 5 7)

seq数値には単純な算術関係があるため、単一のプロセス+いくつかのシェル算術を使用する方が簡単です。

for i in $(seq 1 3); do
  sed -e "s/HAHA/$i/" -e "s/HOHO/$((i+4))/" file.txt
done > new.txt

どちらの場合も、以下を参照してください。シェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?- 提供した最小限の例では非効率性は重要ではないかもしれませんが、より深刻な作業を行う場合は、他のアプローチを使用することを検討する必要があります。

答え2

生成された各行に対して外部ユーティリティを呼び出す必要はありません。

read template <file

paste <(seq 1 3) <(seq 5 7) |
while read x y; do
    t=${template/HAHA/$x}
    t=${t/HOHO/$y}
    printf '%s\n' "$t"
done >new.txt

fileこれは最初にintoという名前のファイルから行を読み込みます$template。次に、ループへの2列入力を設定しますwhile read。ループへの入力はの数字で構成される2つの列ですseq

ループ内でのbash値に対して特定の置換を実行し、$template文字列を読み取った数字に置き換えます。これは生成された後に出力されます。HAHAHOHOpaste$t


を使用awkし、入力が1行だけだとします。

awk '{
         for (i = 1; i <= 3; ++i) {
             t = $0;
             sub("HAHA",   i, t)
             sub("HOHO", 4+i, t)
             print t
         }
     }' file

上記のコードをbash模倣したforループシェル:awk

read template <file

for (( i = 1; i <= 3; ++i )); do
    t=${template/HAHA/$i}
    t=${t/HOHO/$((i+4))}
    printf '%s\n' "$t"
done

関連情報