我写了一个脚本 (replace.sh) 用 ~\n 替换 ~。我想知道如何使用多个参数调用此脚本。
#!/bin/bash
for i in "$*"
do
sed 's/~/~\n/g' "$i"
done
例如我想调用 ./replace.sh text1 text2。它无法读取
text1的内容是:1~1~1。调用脚本后应该是
1 ~
1 ~
1 ~
"$@"
在你的 for 循环中使用:
for i in "$@"
do
sed -i.bak 's/~/~\n/g' "$i"
done
虽然我不确定 sed 是否在做你在这里描述的事情。
这应该足够了:
for i do
sed -i.bak 's/~/~\n/g' "$i"
done
这里的便携式变体应该适用于任何符合 posix 的shell
和sed
:
for i do
sed 's/~/~\n/g' "$i" > "$i.bak" && cp "$i.bak" "$i"
done
注意:in ...
shellfor
循环的部分是可选的。不使用时,for
默认选择所有参数(即"$@"
),这正是您所期望的。
其他答案涵盖了您的真正问题。但值得多说的一件事是双引号时扩展的方式$*
和$@
差异。tl;博士你几乎总是想要"$@"
。
"$*"
扩展为包含所有参数的单个字符串IFS
,参数之间的第一个字符为 。在实践中,这通常意味着所有参数作为一个由空格分隔的字符串。因此,如果您的参数是file1.txt
, file2.txt
,file3.txt
则将其作为一件事"$*"
交给循环,即. 当然,那一件事本身并不存在。file1.txt file2.txt file3.txt
"$@"
扩展到每个参数,一次一个,被视为一个“单词”。file1.txt
这很好,因为它会将file2.txt
前面file3.txt
的示例正确地视为三个项目。循环将一次正确地接收它们。此外,"$@"
这很好,因为即使您的文件名中有空格,您也会得到正确的行为,因为循环将处理,例如,,filename 1
作为三个项目,一项一项。(通常,shell 将空格视为单词结尾的标记,因此在 shell 中看起来像是两个项目,并且.filename 2
filename 2 and a half
filename 1
filename
1
当它们都没有被引用$@
并$*
扩展所有位置参数的单词时。所以在这种情况下,它们实际上是相同的(而且都是一个坏主意,因为它们不能保护你免受奇怪命名的文件的影响)。
这里有一个很好的可视化所有可能性:http ://wiki.bash-hackers.org/scripting/posparams#mass_usage 。