我想迭代给bash脚本的参数,例如:
./bash_script file1 file2 file3
$@
为我提供了给脚本的所有文件但是如何迭代这些文件?
我想cat
每个文件并使用awk
删除内容(我知道如何做到这一点,这是$@
的解包让我感到困惑。)
答案 0 :(得分:5)
诀窍是双引号,如同"$@"
。
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'
,即空格,制表符和换行符)
$ @ vs. $ *
对于任何数组上的任何 @ - 扩展,双引号都是这样的:
$ foo=( "a b" c "d e" )
$ printf ' ->%s\n' "${foo[@]}"
->a b
->c
->d e
相反, * - 扩展(例如,$*
,${foo[*]}
)将使用$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
as
for variable_name; do
done
跳过in something
循环的for
部分意味着in "$@"
。
这甚至也适用于仅支持POSIX的shell(破折号,bourne shell ),它们不具备数组变量但支持"$@"
和"$*
。
答案 1 :(得分:2)
要迭代它们,请使用双引号$@
,如下所示:
for arg in "$@" ; do
echo "--> ${arg}"
done
for arg in "$@"
也可以写为for arg
(甚至是for arg in
),因为bash
手册页指出:
blah blah blah
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
奖励&#34的无用愤怒34;人群: - )
如果您正在考虑以下内容:
cat "${fspec}" | awk 'do something'
然后cat
完全没必要。您可以改为使用:
awk 'do something' "${fspec}"
我通常不担心运行额外流程的(小)低效率,但有些人会这样做。