Shell中的$@和$*的区别

本文通过一个示例脚本详细解释了Shell脚本中$@与$*的区别,包括它们在不同引用情况下如何处理传递给脚本的参数。

我们都知道,在shell中 $@ 和 $* 都会获取传递给脚本或函数时所有的参数。
但其中有细微区别。

接下来,笔者将用一个shell脚本将其中的区别展现给大家。

[root@master scripts]# cat test.sh 
#!/bin/bash

echo '单引号@是:$@'
echo "双引号@是:$@"
echo '单引号*是:$*'
echo "双引号*是:$*"
echo "@没有引号:"$@
echo "*没有引号:"$*

echo '这是双引号$@的遍历'
for i in "$@"
do
    echo $i
done


echo '这是没有引号$@的遍历'
for i in $@
do
    echo $i
done

echo '这是双引号$*的遍历'
for i in "$*"
do
    echo $i
done

echo '这是没有引号$*的遍历'
for i in $*
do
    echo $i
done

在使用 echo 命令时,总共会有3中情况,不加引号、加单引号、加双引号。
单引号的作用:所见即所得,不对内容作任何解析,输入什么,就输出什么。
双引号的作用:对输入内容中的特殊符号进行解析。

由于单引号最终的结果是将原内容重新输出,我们无法区分出 $@ 和 $* 的区别,在此处便没有讨论的意义,所以只有4个循环遍历的结构。

接下来执行脚本,并传递给脚本4个参数 a b c d

sh test.sh a b c d

最终的得到的结果如下:

[root@master scripts]# sh test.sh a b c d
单引号@是:$@
双引号@是:a b c d
单引号*是:$*
双引号*是:a b c d
@没有引号:a b c d
*没有引号:a b c d
这是双引号$@的遍历
a
b
c
d
这是没有引号$@的遍历
a
b
c
d
这是双引号$*的遍历
a b c d
这是没有引号$*的遍历
a
b
c
d

从执行脚本的结果我们不难发现:
1)单引号对变量内容不会作任何解析,所见即所得。
2)加双引号与不加双引号,$@会把所有传递的参数内容输出,并且每个参数个体都是独立的。如脚本结果所示,几个参数,就遍历循环几次。
3)加双引号,$*会把所有传递的参数内容输出,并且将所有参数作为一个整体。如脚本结果所示,4个参数,却只循环遍历了一次;不加双引号,作用与$@相同。
4)一般使用时,尽量还是在echo后面给输出的内容加上引号,一方面是为了更加规范,另一方面是,让我们所写的变量或者特殊符号去发挥它本应起到的作用,就像$@$*一样。

<think>我们之前讨论的是Shell脚本中数组的复制操作,特别是`final_args=("${temp_args[@]}")`的义。现在用户提出了一个新问题:想了解Shell脚本中`$@``$*`的区别。根据用户提供的参考资料,我们需要解释这两者的区别。 参考资料[1][2]提到: - `$@``$*`都表示传递给脚本或函数的所有参数。 - 在没有双引号的情况下,它们的行为一致,都会把所有参数展开为一个以空格分隔的列表。 - 但当它们被双引号引用时,行为就不同了。 参考资料[3][4]进一步说明: - `"$*"`将所有参数合并为一个字符串,参数之间由IFS(内部字段分隔符)的第一个字符分隔(默认为空格)。 - `"$@"`将每个参数分开,每个参数都作为一个独立的字符串。 因此,我们可以这样总结: ### 区别总结 1. **不加双引号**:`$*``$@`没有区别,它们都会将所有位置参数展开为一个单词序列,单词之间用空格分隔。 2. **双引号**: - `"$*"`:将所有位置参数作为一个整体字符串,参数之间用IFS的第一个字符分隔(默认是空格)。例如,`"$*"`等价于`"$1 $2 ... $n"`。 - `"$@"`:将每个位置参数作为独立的字符串,相当于`"$1" "$2" ... "$n"`。 ### 示例说明 假设有一个脚本`test.sh`,内容如下: ```bash #!/bin/bash echo "Using \"\$*\":" for arg in "$*"; do echo "$arg" done echo "Using \"\$@\":" for arg in "$@"; do echo "$arg" done ``` 运行脚本:`./test.sh a b "c d" e` 输出结果: ``` Using "$*": a b c d e # 注意:这里整个参数列表被合并为一个字符串 Using "$@": a b c d # 注意:"c d"被当作一个参数 e ``` ### 重要应用场景 - 当需要将参数原封不动地传递给另一个命令或函数时,应该使用`"$@"`,因为它能保持参数的完整性,特别是当参数空格时。 - 如果想将所有参数合并为一个字符串,则可以使用`"$*"`。 ### 引用说明 在Shell脚本中,正确使用这两个特殊变量对于处理参数至关重要[^1][^2][^3][^4]。 §§相关问题§§ 1. Shell脚本中如何正确处理带空格的参数?[^2] 2. `$*``$@`在函数中传递参数时有何注意事项?[^3] 3. IFS变量如何影响`"$*"`的输出?[^4] </think>### Shell 脚本中 `$@` `$*` 的区别详解 在 Shell 脚本中,`$@` `$*` 都用于引用脚本或函数的所有参数,但它们在**参数处理方式****使用场景**上有本质区别: | 特性 | `$*` | `$@` | |--------------|-------------------------------------|-------------------------------------| | **本质** | 将参数合并为**单个字符串** | 将参数保持为**独立元素** | | **引号效果** | `"$*"` = `"$1 $2 ... $n"`(单字符串) | `"$@"` = `"$1" "$2" ... "$n"`(多字符串) | | **默认行为** | 无引号时等同`$@`(空格分隔) | 无引号时等同`$*`(空格分隔) | | **循环遍历** | `for arg in "$*"` 只循环**1次** | `for arg in "$@"` 循环**n次** | | **适用场景** | 需合并参数的场景(如日志拼接) | 需保留参数独立性的场景(如命令传参)| --- #### 1. 核心区别参数独立性 - **`$*`** 将所有参数视为**单个字符串**参数间用**空格**连接(可通过`IFS`修改): ```bash echo "$*" # 输出: arg1 arg2 arg3 ``` - **`$@`** 将每个参数视为**独立字符串**,保留原始分隔: ```bash echo "$@" # 输出: arg1 arg2 arg3(视觉相似,但内存结构不同) ``` > 关键验证:当参数空格时差异显著(例如 `./script.sh "file 1.txt" "file 2.txt"`) --- #### 2. 双引号下的关键差异 😎 ```bash #!/bin/bash # 示例:./demo.sh "Hello World" "Shell Script" # $*双引号行为 echo "Using \"\$*\":" for arg in "$*"; do echo "[$arg]" # 只循环一次!输出: [Hello World Shell Script] done # $@双引号行为 echo "Using \"\$@\":" for arg in "$@"; do echo "[$arg]" # 循环两次!输出: [Hello World] [Shell Script] done ``` **输出结果**: ``` Using "$*": [Hello World Shell Script] Using "$@": [Hello World] [Shell Script] ``` --- #### 3. 应用场景对比 - **使用 `"$@"` 的场景** 需保留参数原始结构的操作,如将参数透传给其他命令: ```bash # 正确!保留带空格的文件名 grep "pattern" "$@" ``` - **使用 `"$*"` 的场景** 需合并参数的场景,如生成日志消息: ```bash # 将所有参数合并为一行日志 echo "[$(date)] 参数: $*" >> log.txt ``` --- #### 4. 技术原理图 ``` 参数传递: ("arg1" "arg two" "arg3") │ ├─ "$*" → "arg1 arg two arg3" (单字符串,空格连接) │ └─ "$@" → ("arg1" "arg two" "arg3") (独立字符串数组) ``` > 通过 `${#@}` 可获取参数数量,通过 `shift` 可逐个处理参数[^2] --- ### 总结建议 1. **优先使用 `"$@"`** 适用于 99% 的参数处理场景,能正确处理带空格/特殊字符的参数[^3][^4] 2. **慎用无引号的 `$*` 或 `$@`** 无引号时二者行为相同(空格分隔),但会拆分空格的参数 3. **修改 `IFS` 可定制 `"$*"` 的分隔符** ```bash IFS="|" && echo "$*" # 输出: arg1|arg2|arg3 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值