我想迭代给bash脚本的参数,例如:
./bash_script file1 file2 file3
$@
给了我所有给脚本的文件,但我如何遍历这些文件?
我想cat
每个文件并删除使用awk
的内容(我知道如何做到这一点,这是$@
的解包,这让我感到困惑)。
技巧是将与"$@"
中双引号。
foo(){
printf ' ->%sn' "$@";
}
foo "a b" c "d e"
等价于:
printf ' ->%sn' "a b" c "d e"
如果上面的$@
是而不是双引号,那么您将得到:
printf ' ->%sn' a b c d e
由于$IFS
字符的分词($IFS
默认为' '$'t'$'n'
,即空格,制表符和换行符)
$@ vs. $*
对于任意数组:上的任意@-expansion,双引号就像这样工作$ foo=( "a b" c "d e" )
$ printf ' ->%sn' "${foo[@]}"
->a b
->c
->d e
相反,*-展开(例如,$*
, ${foo[*]}
)将使用$IFS
的第一个字符将数组中的元素连接成一个字符串:
$ foo=( "a b" c "d e" )
$ ( IFS=:; printf ' ->%sn' "${foo[*]}" )
->a b:c:d e
如果不加引号,它将再次在这个IFS字符上分裂:
$ foo=( "a b" c "d e:f:g" )
$ ( IFS=:; printf ' ->%sn' ${foo[*]} )
->a b
->c
->d e
->f
->g
for循环中遍历$@的技巧:
"$@"
数组是特殊的。如果要在for循环中遍历"$@"
,则可以缩写为
for variable_name in "$@"; do
...
done
for variable_name; do
done
表示跳过for
循环的in something
部分意味着in "$@"
。
这也适用于仅posix shell (dash, bourne shell),这些shell没有数组变量,但支持"$@"
和"$*
。
要遍历它们,可以使用双引号括起来的$@
,如下所示:
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命令对设置的每个位置参数执行一次列表。
但是,我更喜欢显式的变体。
下面的文字记录显示了这一点:
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}"
我通常不担心运行额外进程的(小)效率低下,但有些人会。