在 for 循环中使用 sed 创建多个输入文件

在 for 循环中使用 sed 创建多个输入文件

假设我有一个名为“am”的简单 Mathematica 脚本文件,其中包含未分配值的参数“a”:

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

我想做的是通过将值“a”从 1 更改为 10 来创建多个脚本文件,并通过相应的“a”值命名每个文件,例如 1.m、2.m 等。为此,我尝试按以下方式在 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

Shell 脚本包含大量文字字符串(命令名、文件名等),因此使用变量的值需要一个字符来显式标记它是变量引用:参数扩展$由后跟变量名(最简单的形式)组成。一般来说,变量替换需要双引号。在单引号内,变量根本不扩展($内部'…'仅代表其自身)。因此:

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

sed我认为在只有一个可以调用的情况下调用如此多的 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将其输出打印到标准输出 w将其输出写入一个或多个命名文件。当 shell 循环工作时,它会打印行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. g全局地用 shell 变量的当前值替换编辑缓冲区中出现s///的每个字母。a$a
  3. 同时p还将该替换的结果打印s///到标准输出并将w结果写入名为/tmp/$a.mwhere $ais an iterable 的文件。
  4. 最后g通过覆盖编辑缓冲区来设置保持缓冲区。

sed将把该序列应用于其命名的输入文件中的每一行。首次调用时,它将截断其命名的每个write 文件,但随后会w按顺序将每个 rite 操作附加到每个输出文件中。但由于我只有一行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,从 中新创建的十个文件中的每一个中读取/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

相关内容