5

我写了一个脚本 (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 ~
4

3 回答 3

4

"$@"在你的 for 循环中使用:

for i in "$@"
do
   sed -i.bak 's/~/~\n/g' "$i"
done

虽然我不确定 sed 是否在做你在这里描述的事情。

于 2013-08-21T21:04:33.847 回答
2

这应该足够了:

for i do
  sed -i.bak 's/~/~\n/g' "$i"
done

这里的便携式变体应该适用于任何符合 posix 的shellsed

for i do
  sed 's/~/~\n/g' "$i" > "$i.bak" && cp "$i.bak" "$i"
done

注意:in ...shellfor循环的部分是可选的。不使用时,for默认选择所有参数(即"$@"),这正是您所期望的。

于 2013-08-21T21:16:11.117 回答
1

其他答案涵盖了您的真正问题。但值得多说的一件事是双引号时扩展的方式$*$@差异。tl;博士你几乎总是想要"$@"

"$*"扩展为包含所有参数的单个字符串IFS,参数之间的第一个字符为 。在实践中,这通常意味着所有参数作为一个由空格分隔的字符串。因此,如果您的参数是file1.txt, file2.txtfile3.txt则将其作为一件事"$*"交给循环,即. 当然,那一件事本身并不存在。file1.txt file2.txt file3.txt

"$@"扩展到每个参数,一次一个,被视为一个“单词”。file1.txt这很好,因为它会将file2.txt前面file3.txt的示例正确地视为三个项目。循环将一次正确地接收它们。此外,"$@"这很好,因为即使您的文件名中有空格,您也会得到正确的行为,因为循环将处理,例如,,filename 1作为三个项目,一项一项。(通常,shell 将空格视为单词结尾的标记,因此在 shell 中看起来像是两个项目,并且.filename 2filename 2 and a halffilename 1filename1

当它们都没有被引用$@$*扩展所有位置参数的单词时。所以在这种情况下,它们实际上是相同的(而且都是一个坏主意,因为它们不能保护你免受奇怪命名的文件的影响)。

这里有一个很好的可视化所有可能性:http ://wiki.bash-hackers.org/scripting/posparams#mass_usage 。

于 2013-08-21T21:39:24.477 回答