访问bash命令行args $ @ vs $*

Oz1*_*123 298 bash command-line-arguments

在许多SO问题和bash教程中,我看到我可以通过两种方式访问​​bash脚本中的命令行参数:

$ ~ >cat testargs.sh 
#!/bin/bash

echo "you passed me" $*
echo "you passed me" $@
Run Code Online (Sandbox Code Playgroud)

结果如下:

$ ~> bash testargs.sh arg1 arg2
you passed me arg1 arg2
you passed me arg1 arg2
Run Code Online (Sandbox Code Playgroud)

$*和之间有什么区别$@
应该何时使用前者,何时使用后者?

gle*_*man 395

引用特殊参数时会出现差异.让我说明一下差异:

$ set -- "arg  1" "arg  2" "arg  3"

$ for word in $*; do echo "$word"; done
arg
1
arg
2
arg
3

$ for word in $@; do echo "$word"; done
arg
1
arg
2
arg
3

$ for word in "$*"; do echo "$word"; done
arg  1 arg  2 arg  3

$ for word in "$@"; do echo "$word"; done
arg  1
arg  2
arg  3
Run Code Online (Sandbox Code Playgroud)

关于引用重要性的另一个例子:注意"arg"和数字之间有2个空格,但如果我没有引用$ word:

$ for word in "$@"; do echo $word; done
arg 1
arg 2
arg 3
Run Code Online (Sandbox Code Playgroud)

在bash中,"$@"是迭代的"默认"列表:

$ for word; do echo "$word"; done
arg  1
arg  2
arg  3
Run Code Online (Sandbox Code Playgroud)

  • +1我一直认为这个概念最好通过一个简单的例子来证明,其中bash手册是完全缺乏的. (61认同)
  • @Segfault,在这种情况下,总是选择带引号的"$ @"`. (6认同)
  • 是否有可能的用例,当需要`$*`或`'$*"`时,目的不能由`$ @`或`'$ @"`来提供? (5认同)
  • 哪个版本更适合"包装"脚本,其中脚本参数需要成为新命令的参数? (5认同)
  • 是的,完全如此处所示:仅在引用时. (4认同)
  • 这个答案包含有用的例子,但如果它也解释了它们背后的机制会更好.*为什么*它是这样的? (2认同)
  • bash 是一种奇怪的语言。在很多方面,我认为它受到与 40 多年历史的 Bourne shell 的兼容性的限制 (2认同)

Ser*_*ndt 225

来自Bash Hackers Wiki的一个非常方便的概述表:

$*对$ @表

其中c第三行中是的第一个字符$IFS,内部字段分隔符; 环境变量.

如果参数要存储在脚本变量中并且参数应该包含空格,我全心全意地建议使用一个"$*"技巧,将内部字段分隔符$IFS设置为tab.

  • ...其中"c"是$ IFS的第一个字符 (41认同)
  • ...和`$ IFS`代表"内部字段分隔符". (38认同)
  • @MarinosAn 使用 `"$@"` (带引号)。其他变体都不起作用 (4认同)
  • 假设我想创建一个包装器脚本,它除了模仿包装命令的功能外什么也不做。我应该使用哪种语法将参数从包装器脚本传递到内部命令? (2认同)

Muf*_*ffo 43

$*

从1开始扩展到位置参数.当扩展发生在双引号内时,它会扩展为单个单词,每个参数的值由IFS特殊变量的第一个字符分隔.也就是说,"$*"相当于"$ 1c $ 2c ...",其中c是IFS变量值的第一个字符.如果未设置IFS,则参数由空格分隔.如果IFS为null,则连接参数时不会插入分隔符.

$ @

从1开始扩展到位置参数.当扩展发生在双引号内时,每个参数都会扩展为单独的单词.也就是说,"$ @"相当于"$ 1""$ 2"...如果双引号扩展发生在一个单词中,则第一个参数的扩展与原始单词的开头部分连接,并且扩展最后一个参数与原始单词的最后一部分连接在一起.当没有位置参数时,"$ @"和$ @扩展为空(即,它们被删除).

资料来源:Bash man


rko*_*egi 15

$ @与$*相同,但每个参数都是带引号的字符串,也就是说,参数是完整传递的,没有解释或扩展.这意味着,参数列表中的每个参数都被视为一个单独的单词.

当然,应该引用"$ @".

http://tldp.org/LDP/abs/html/internalvariables.html#ARGLIST