如何迭代Bash脚本中的参数
我有一个复杂的命令,我想创建一个shell / bash脚本。 我可以很容易地以$1
的$1
写出来:
foo $1 args -o $1.ext
我希望能够将多个输入名称传递给脚本。 什么是正确的做法?
当然,我想处理其中有空格的文件名。
使用"$@"
来表示所有参数:
for var in "$@"
do
echo "$var"
done
这将迭代每个参数并将其打印在单独的行上。 $ @的行为与$ *相似,除了引用时,如果参数中有空格,则正确分解参数:
sh test.sh 1 2 '3 4'
1
2
3 4
重写VonC现在删除的答案。
Robert Gamble简洁的回答直接解决了这个问题。 这个放大了一些与包含空格的文件名有关的问题。
另请参阅:/ bin / sh中的$ {1:+“$ @”}
基础论文: "$@"
是正确的, $*
(无引号)几乎总是错的。 这是因为当参数包含空格时, "$@"
可以正常工作,当它们不包含空格时与$*
的作用相同。 在某些情况下, "$*"
也可以,但"$@"
通常(但不总是)在相同的地方工作。 不加引号, $@
和$*
是等价的(并且几乎总是错误的)。
那么, $*
, $@
, "$*"
和"$@"
之间的区别是什么? 它们都与'壳的所有论点'有关,但它们做不同的事情。 当没有引用时, $*
和$@
做同样的事情。 他们将每个“单词”(非空白序列)视为一个单独的参数。 不过,引用的表单有很大不同: "$*"
将参数列表视为一个单独的空格分隔的字符串,而"$@"
将参数与命令行中指定的参数几乎完全相同。 当没有位置参数时, "$@"
扩展到什么都没有; "$*"
扩展为一个空字符串 - 是的,有一个区别,虽然它很难察觉它。 见下文的详细信息,在引入(非标准)的命令之后al
。
第二篇论文:如果你需要用空格处理参数然后将它们传递给其他命令,那么你有时需要非标准的工具来协助。 (或者你应该小心使用数组: "${array[@]}"
行为类似于"$@"
。)
例:
$ mkdir "my dir" anotherdir
$ ls
anotherdir my dir
$ cp /dev/null "my dir/my file"
$ cp /dev/null "anotherdir/myfile"
$ ls -Fltr
total 0
drwxr-xr-x 3 jleffler staff 102 Nov 1 14:55 my dir/
drwxr-xr-x 3 jleffler staff 102 Nov 1 14:55 anotherdir/
$ ls -Fltr *
my dir:
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 14:55 my file
anotherdir:
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 14:55 myfile
$ ls -Fltr "./my dir" "./anotherdir"
./my dir:
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 14:55 my file
./anotherdir:
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 14:55 myfile
$ var='"./my dir" "./anotherdir"' && echo $var
"./my dir" "./anotherdir"
$ ls -Fltr $var
ls: "./anotherdir": No such file or directory
ls: "./my: No such file or directory
ls: dir": No such file or directory
$
为什么这不起作用? 它不起作用,因为shell在扩展变量之前会处理引号。 所以,为了让shell注意$var
嵌入的引号,你必须使用eval
:
$ eval ls -Fltr $var
./my dir:
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 14:55 my file
./anotherdir:
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 14:55 myfile
$
如果你有文件名,例如“ He said, "Don't do this!"
“(带引号和双引号和空格),这会变得非常棘手。
$ cp /dev/null "He said, "Don't do this!""
$ ls
He said, "Don't do this!" anotherdir my dir
$ ls -l
total 0
-rw-r--r-- 1 jleffler staff 0 Nov 1 15:54 He said, "Don't do this!"
drwxr-xr-x 3 jleffler staff 102 Nov 1 14:55 anotherdir
drwxr-xr-x 3 jleffler staff 102 Nov 1 14:55 my dir
$
这些shell(所有这些)并不会让它很容易处理这些东西,所以很多Unix程序在处理它们的时候并没有很好的处理。 在Unix上,文件名(单个组件)可以包含除斜杠和NUL '