我想迭代给 bash 脚本的参数,例如:
./bash_script file1 file2 file3
$@
给了我所有给脚本的文件,但我如何迭代这些文件?
我想使用cat
每个文件并删除内容awk
(我知道该怎么做,这是解包$@
让我感到困惑)。
我想迭代给 bash 脚本的参数,例如:
./bash_script file1 file2 file3
$@
给了我所有给脚本的文件,但我如何迭代这些文件?
我想使用cat
每个文件并删除内容awk
(我知道该怎么做,这是解包$@
让我感到困惑)。
诀窍是双引号,如"$@"
.
foo(){
printf ' ->%s\n' "$@";
}
foo "a b" c "d e"
相当于:
printf ' ->%s\n' "a b" c "d e"
如果$@
上面的不是双引号,那么你会得到:
printf ' ->%s\n' a b c d e
由于对$IFS
字符进行分词($IFS
默认为' '$'\t'$'\n'
,即空格、制表符和换行符)
$@ 与 $*
对于任何数组上的任何@-expansion ,双引号的工作方式如下:
$ foo=( "a b" c "d e" )
$ printf ' ->%s\n' "${foo[@]}"
->a b
->c
->d e
相比之下,*-expansions(例如,, $*
)${foo[*]}
将使用第一个字符 of$IFS
将数组的项连接成单个字符串:
$ foo=( "a b" c "d e" )
$ ( IFS=:; printf ' ->%s\n' "${foo[*]}" )
->a b:c:d e
如果不加引号,它将再次在这个 IFS 字符上分裂:
$ foo=( "a b" c "d e:f:g" )
$ ( IFS=:; printf ' ->%s\n' ${foo[*]} )
->a b
->c
->d e
->f
->g
在 for 循环中迭代 $@ 的技巧:
"$@"
数组很特别。如果你想在 for 循环中迭代"$@"
,那么你可以缩写
for variable_name in "$@"; do
...
done
作为
for variable_name; do
done
正如跳过循环的in something
一部分所for
暗示的那样in "$@"
。
这甚至适用于仅 POSIX 的 shell(dash、bourne shell),它们没有数组变量但支持"$@"
and "$*
。
要遍历它们,请使用双引号$@
,如下所示:
for arg in "$@" ; do
echo "--> ${arg}"
done
for arg in "$@"
也可以写为for arg
(甚至) ,for arg in
因为bash
手册页指出:
for name [ [ in [ word ... ] ] ; ] do list ; done
等等等等等等
如果省略 in 字,for 命令对设置的每个位置参数执行一次 list。
但是,我更喜欢显式变体。
以下记录显示了这一点:
pax: testprog.sh 1 2 3 '4 5' '' '6 7 8' "9"
--> 1
--> 2
--> 3
--> 4 5
-->
--> 6 7 8
--> 9
而且,顺便说一句,您关于使用cat
和awk
修改文件的评论可能会降低“无用cat
奖励”人群的愤怒:-)
如果您正在考虑类似的事情:
cat "${fspec}" | awk 'do something'
那么cat
是完全没有必要的。您可以改为使用:
awk 'do something' "${fspec}"
我通常不担心运行额外进程的(小)效率低下,但有些人会这样做。