sedコマンドに "$i"とforループを追加するには?

sedコマンドに "$i"とforループを追加するには?
for (( i=30; i<=44; i++))
do
sed -i '28s/0.340d0/0."$i"0d0/' 1.txt 
mv 1.txt "$i".txt     
done

しかし、実行すると動作しません。 sed コマンド "$i" ループ内では動作しません。助けてください。 1.txtファイルの28行目の数字0.340doが、コピーされたファイルの0.30d0から0.440d0に置き換えられます。

答え1

コードには3つの問題があります。

  1. 一重引用符で囲まれた文字列をsed式として使用して、シェルがコマンドの代替セクションで変数を拡張するのを防ぎますs///

  2. 元のファイル1.txtはその場所で変更されるため、シェルが変数を拡張してもループを介してパターンが2番目に一致しません(以前の反復でファイルが変更されたため)。

  3. 1.txt最初の反復でファイルを移動すると、各sed後続の反復で「該当するファイルまたはディレクトリがありません」というエラーでコマンドが失敗します。

次の3つの問題を解決してください。

for number in {30..44}; do
    sed '28 s/0\.340d0/0.'"$number"'0d0/' 1.txt >"$number.txt"
done

また、パターンの点が揃っていることを確認してください。言葉文字の代わりにドットを使用します(.エスケープまたは未使用の場合に\.実行されます[.])。式にはまだ一重引用符を使用していますが、一時的に破棄してシェル変数にsed二重引用符の値を導入していますnumber

コマンドの結果は、変数をsed使用してnumber名前付きファイルに書き込まれます。

文字列で始まるという事実を使用することもできますrmin=(これは次のように仮定されます)。ただこの文字列で始まる行):

for number in {30..44}; do
    sed 's/^rmin=.*/rmin=0.'"$number"'0d0/' 1.txt >"$number.txt"
done

以下を使用すると、同じ操作をより簡潔に実行できますawk

for number in {30..44}; do
    awk -v num="$number" 'FNR == 28 { printf "rmin=0.%.2d0d0\n", num; next }; 1' 1.txt >"$number.txt"
done

この方法の利点は、数値が10より小さい場合でも数値を正しく挿入することです(たとえば、forの代わりに0.020d0create 0.20d0)。2

または行rmin=の先頭から一致させます。

for number in {30..44}; do
    awk -v num="$number" '/^rmin=/ { printf "rmin=0.%.2d0d0\n", num; next }; 1' 1.txt >"$number.txt"
done

答え2

引用符のため、変数は30、31、32などではなく文字通り'解釈されます。$i

sed式全体を引用符で囲むために、次のように変更しました"

for (( i=30; i<=44; i++))
do
sed "s/0.340d0/0.${i}0d0/g" 1.txt > temp.txt
cp temp.txt "$i".txt     
done

関連情報