forループでsedを使用して複数の入力ファイルを作成する

forループでsedを使用して複数の入力ファイルを作成する

値が割り当てられていないパラメータ「a」を含む「am」という単純なMathematicaスクリプトファイルがあるとします。

Solve[x^2+5^a==0,x]>>a.out

私が望むのは、「a」値を1から10に変更して複数のスクリプトファイルを作成し、1.m、2.mなどの対応する「a」値で各ファイルの名前を指定することです。これを行うには、次のようにforループで 'sed'コマンドを使用してみました。

for ((i=1; i<=10; i++)); do sed 's/a/i/' <a.m >i.m;  done

これにより、iの固定値ごとに「a」が数値に変わり、「im」という新しいファイルが作成されます。ただし、上記の行は im という単一のスクリプトファイルを生成します。ここで、「a」は「i」に置き換えられます。どんな提案がありますか?

答え1

シェルスクリプトには多くのリテラル文字列(コマンド名、ファイル名など)が含まれているため、変数値を使用するには変数参照として明示的に表示する文字が必要です。パラメータ拡張$その後に変数名が続きます(最も単純な形式)。通常、変数の置換には二重引用符が必要です。。一重引用符内では、変数はまったく拡張されません($内部的には'…'それ自体を表す)。したがって:

for ((i=1; i<=10; i++)); do
  sed "s/a/$i/" <a.m >"$i.m"
done

二重括弧内には、二重括弧が算術式を区別し、算術式に文字列がないため、単純な単語は逆参照変数として解釈されるため、ドル記号は必要ありません。

sed コマンドは、aテンプレートファイルの最初の文字を置き換えます。他の名前(関数名など)には表示されない変数名を選択できます。または、スクリプトの先頭から割り当てを作成することもできます。

for ((i=1; i<=10; i++)); do
  echo "a=$i;" >"$i.m"
  cat a.m >>"$i.m"
done

リダイレクト演算子>>以下を使用して既存のファイルに追加します。>ファイルが存在する場合は切り捨てられます。

答え2

sed1つしか呼び出せませんが、あまりにも多くのsを呼び出すのは間違っていると思います。sed入力を効果的に繰り返し、それを別の出力に変更する機能で有名です。多くの種類エクスポートも非常に簡単です。たとえば、ここではPOSIXポータブルです。(そしてより効率的)ループを再作成してくださいfor

echo "Solve[x^2+5^a==$((a=0)),x]>>a.out" >/tmp/i.m    ###create file + init $a
until [ "$((a+=1))" -gt 10 ]                          ###iterate + test
do    printf "h;s/a/$a/gpw /tmp/$a.m\ng;"             ###push new sed command
done| sed -nf - /tmp/i.m                              ###read + apply commands
head /tmp/[0-9].m /tmp/10.m                           ###print results

sedこれらのスクリプトはstdinで読み取られ、名前付きファイルに適用できます。これがすぐ上のsed -nf - /tmp/i.mステートメントが実行するアクションです。同時に、p出力を標準出力として印刷することもできます。そして w1つ以上の名前付きファイルに出力を書き込みます。シェルループが機能すると行が印刷され、sed完了すると合計は次のようになります。

h;s/a/1/gpw /tmp/1.m
g;h;s/a/2/gpw /tmp/2.m
g;h;s/a/3/gpw /tmp/3.m
g;h;s/a/4/gpw /tmp/4.m
g;h;s/a/5/gpw /tmp/5.m
g;h;s/a/6/gpw /tmp/6.m
g;h;s/a/7/gpw /tmp/7.m
g;h;s/a/8/gpw /tmp/8.m
g;h;s/a/9/gpw /tmp/9.m
g;h;s/a/10/gpw /tmp/10.m
g

これは教えてくれるsed...

  1. h編集バッファのコピーで古いバッファを上書きします。
  2. gs///編集バッファ内の各文字をシェル変数の現在の値でグローバルに置き換えます。a$a
  3. また、p代替結果をs///標準出力として印刷し、結果を反復可能wファイルである/tmp/$a.m場所に記録します。$a
  4. 最後に、g編集バッファを上書きして保持バッファを設定します。

sedこの順序は、名前付き入力ファイルの各行に適用されます。最初に呼び出されると、名前付きの各writeファイルが切り捨てられますが、次にw各riteジョブを各出力ファイルに順番に追加します。ただし、1行しかないため、次i.mのようsedに印刷されます。

Solve[x^2+5^1==0,x]>>1.out
Solve[x^2+5^2==0,x]>>2.out
Solve[x^2+5^3==0,x]>>3.out
Solve[x^2+5^4==0,x]>>4.out
Solve[x^2+5^5==0,x]>>5.out
Solve[x^2+5^6==0,x]>>6.out
Solve[x^2+5^7==0,x]>>7.out
Solve[x^2+5^8==0,x]>>8.out
Solve[x^2+5^9==0,x]>>9.out
Solve[x^2+5^10==0,x]>>10.out

そして、head新しく作成された10個のファイルのそれぞれを読み取り、次のものを/tmp印刷します。

==> /tmp/1.m <==
Solve[x^2+5^1==0,x]>>1.out

==> /tmp/2.m <==
Solve[x^2+5^2==0,x]>>2.out

==> /tmp/3.m <==
Solve[x^2+5^3==0,x]>>3.out

==> /tmp/4.m <==
Solve[x^2+5^4==0,x]>>4.out

==> /tmp/5.m <==
Solve[x^2+5^5==0,x]>>5.out

==> /tmp/6.m <==
Solve[x^2+5^6==0,x]>>6.out

==> /tmp/7.m <==
Solve[x^2+5^7==0,x]>>7.out

==> /tmp/8.m <==
Solve[x^2+5^8==0,x]>>8.out

==> /tmp/9.m <==
Solve[x^2+5^9==0,x]>>9.out

==> /tmp/10.m <==
Solve[x^2+5^10==0,x]>>10.out

関連情報