たとえば、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
文字列を読み取った数字に置き換えます。これは生成された後に出力されます。HAHA
HOHO
paste
$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