假设我有一个名为“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
...
h
用其编辑缓冲区的副本覆盖其旧缓冲区。g
全局地用 shell 变量的当前值替换编辑缓冲区中出现s///
的每个字母。a
$a
- 同时
p
还将该替换的结果打印s///
到标准输出并将w
结果写入名为/tmp/$a.m
where$a
is an iterable 的文件。 - 最后
g
通过覆盖编辑缓冲区来设置保持缓冲区。
sed
将把该序列应用于其命名的输入文件中的每一行。首次调用时,它将截断其命名的每个w
rite 文件,但随后会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