2

我想迭代给 bash 脚本的参数,例如:

./bash_script file1 file2 file3

$@给了我所有给脚本的文件,但我如何迭代这些文件?

我想使用cat每个文件并删除内容awk(我知道该怎么做,这是解包$@让我感到困惑)。

4

2 回答 2

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',即空格、制表符和换行符)


$@ 与 $*

对于任何数组上的任何@-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 "$*

于 2016-06-28T01:11:14.120 回答
2

要遍历它们,请使用双引号$@,如下所示:

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

而且,顺便说一句,您关于使用catawk修改文件的评论可能会降低“无用cat奖励”人群的愤怒:-)

如果您正在考虑类似的事情:

cat "${fspec}" | awk 'do something'

那么cat是完全没有必要的。您可以改为使用:

awk 'do something' "${fspec}"

我通常不担心运行额外进程的(小)效率低下,但有些人会这样做。

于 2016-06-28T01:14:28.543 回答