当前位置: 首页 > news >正文

Shell 中 $@ 与 $* 的核心区别:双引号包裹下的关键差异解析

Shell 中 $@ 与 $* 的核心区别:双引号包裹下的关键差异解析

  • Shell 中 $@ 与 $* 的核心区别:双引号包裹下的关键差异解析
    • 一、核心结论:先明确“有无双引号”的影响
    • 二、案例对比:用实际脚本看差异
      • 案例1:参数中不含空格——两者表现一致
        • 脚本代码:
        • 执行结果:
        • 分析:
      • 案例2:参数中包含空格——差异彻底显现
        • 脚本代码:
        • 执行结果:
        • 分析:
      • 案例3:结合参数个数($#)看差异
        • 脚本代码:
        • 执行结果:
        • 关键结论:
    • 三、底层原理:为什么会有差异?
    • 四、适用场景:什么时候用 $@,什么时候用 $*?
      • 1. 优先用`"$@"`的场景(90%以上的情况)
      • 2. 仅用`"$*"`的特殊场景
    • 五、总结:一句话记住差异

Shell 中 $@ 与 $* 的核心区别:双引号包裹下的关键差异解析

在 Shell 脚本函数传参或处理命令行参数时,$@$*是两个常用的“全参数”变量,都能获取所有传入的参数。但当用双引号包裹时,两者的行为会产生本质区别——这也是很多人混淆的关键点,甚至可能导致脚本逻辑出错。今天就从原理、案例、场景三个维度,彻底讲清它们的差异。

一、核心结论:先明确“有无双引号”的影响

在深入分析前,先记住一个核心规则:

  • 不包裹双引号时$@$*行为完全一致,都会将所有参数按“空格分隔”拆分成独立的“参数单元”,相当于$1 $2 $3 ...
  • 包裹双引号时:两者差异彻底显现(这是日常使用中最需要关注的场景):
    • "$@"保留参数的原始结构,将每个参数视为一个独立单元,即使参数中包含空格,也不会被拆分;
    • "$*"将所有参数合并成一个整体,用IFS(Shell默认分隔符,通常是空格)连接所有参数,最终只生成一个“大参数”。

简单说:"$@"是“逐个保留参数”,"$*"是“合并所有参数”——这是两者最本质的区别。

二、案例对比:用实际脚本看差异

光看理论不够直观,我们通过3个具体案例,对比双引号包裹下$@$*的实际表现(以Bash脚本为例)。

案例1:参数中不含空格——两者表现一致

当传入的参数没有空格时,"$@""$*"的输出看起来相同,但底层处理逻辑不同(只是结果巧合一致)。

脚本代码:
#!/bin/bash
# 定义函数,分别打印"$@"和"$*"的处理结果
test_params() {echo "=== 用\"$@\"处理参数 ==="# 循环遍历参数,查看每个参数单元for param in "$@"; doecho "参数单元:$param"doneecho -e "\n=== 用\"$*\"处理参数 ==="for param in "$*"; doecho "参数单元:$param"done
}# 调用函数,传入3个无空格参数
test_params "Linux" "Shell" "Function"
执行结果:
=== 用"$@"处理参数 ===
参数单元:Linux
参数单元:Shell
参数单元:Function=== 用"$*"处理参数 ===
参数单元:Linux Shell Function
分析:
  • "$@":将3个参数拆分为3个独立单元,循环执行3次,分别输出每个参数;
  • "$*":将3个参数合并成"Linux Shell Function"一个单元,循环只执行1次,输出合并后的整体。

案例2:参数中包含空格——差异彻底显现

当参数本身包含空格(如"Hello World")时,"$@"能保留参数的原始结构,而"$*"会破坏结构——这是日常使用中最容易踩坑的场景。

脚本代码:
#!/bin/bash
test_params() {echo "=== 用\"$@\"处理参数 ==="for param in "$@"; doecho "参数单元:$param"doneecho -e "\n=== 用\"$*\"处理参数 ==="for param in "$*"; doecho "参数单元:$param"done
}# 调用函数,传入2个含空格的参数
test_params "Hello World" "Bash Script"
执行结果:
=== 用"$@"处理参数 ===
参数单元:Hello World
参数单元:Bash Script=== 用"$*"处理参数 ===
参数单元:Hello World Bash Script
分析:
  • "$@":正确识别2个参数("Hello World""Bash Script"),即使参数内有空格,也不会拆分,完美保留原始意图;
  • "$*":将2个参数合并成"Hello World Bash Script"一个单元,原本的2个参数被“拆成”1个,完全破坏了参数结构——这通常不是我们想要的结果。

案例3:结合参数个数($#)看差异

$#用于获取参数的总个数,结合"$@""$*"时,也能直观看到两者的差异。

脚本代码:
#!/bin/bash
test_params() {echo "用\"$@\"时,参数总个数:$#"echo "用\"$*\"时,参数总个数:$#"  # 注意:$#的计算依据是原始参数个数,与$@/$*无关echo -e "\n=== 循环遍历\"$@\" ==="count=0for param in "$@"; docount=$((count+1))doneecho "循环执行次数:$count"echo -e "\n=== 循环遍历\"$*\" ==="count=0for param in "$*"; docount=$((count+1))doneecho "循环执行次数:$count"
}# 传入3个参数(含1个空格参数)
test_params "A" "B C" "D"
执行结果:
用"$@"时,参数总个数:3
用"$*"时,参数总个数:3=== 循环遍历"$@" ===
循环执行次数:3=== 循环遍历"$*" ===
循环执行次数:1
关键结论:
  • $#的数值只取决于原始传入的参数个数(本例中是3个),与用$@还是$*处理无关;
  • 但循环遍历时,"$@"的执行次数等于$#(逐个处理参数),而"$*"的执行次数永远是1(合并成一个参数)。

三、底层原理:为什么会有差异?

理解底层逻辑能帮你更深刻地记住差异:

  • "$@":相当于"$1" "$2" "$3" ...,即把每个原始参数用双引号包裹后依次列出,所以能保留每个参数的独立性(包括参数内的空格);
  • "$*":相当于"$1$IFS$2$IFS$3...",即把所有参数用IFS(默认是空格)连接成一个字符串,再用双引号包裹,所以最终只有一个参数单元。

其中IFS(Internal Field Separator)是Shell的内部分隔符,默认值为“空格+制表符+换行符”,若修改IFS"$*"的合并结果也会变化(比如IFS=,时,参数会用逗号连接)。
IFS 更多介绍,见《彻底理解 Shell 中的 IFS:内部分隔符的作用与应用》

四、适用场景:什么时候用 $@,什么时候用 $*?

根据两者的差异,日常使用中需明确场景选择:

1. 优先用"$@"的场景(90%以上的情况)

只要需要保留参数的原始结构,尤其是参数中可能包含空格时,必须用"$@"

  • 函数传参后需要循环处理每个参数(如批量打印、批量操作文件);
  • 脚本接收命令行参数后,需要逐个解析参数(如./script.sh "file 1.txt" "file 2.txt");
  • 调用其他命令时,需要将参数原样传递(如cp "$@" /target/,确保每个文件参数正确)。

简单说:日常写脚本,只要涉及“处理多个独立参数”,就用"$@",这是最安全、最符合直觉的选择。

2. 仅用"$*"的特殊场景

只有当需要将所有参数合并成一个字符串时,才用"$*"

  • 生成日志信息时,将所有参数拼接成一句完整的描述(如echo "执行命令:$0 $*");
  • 将参数作为一个整体传递给需要“单字符串输入”的命令(如echo "$*" > log.txt,将所有参数写入文件一行)。

例如:

#!/bin/bash
# 记录脚本执行时的所有参数(合并成一行日志)
log_params() {local timestamp=$(date "+%Y-%m-%d %H:%M:%S")# 用"$*"合并参数,写入日志echo "[$timestamp] 执行参数:$*" >> script.log
}# 调用函数,传入多个参数(含空格)
log_params "start" "backup data" "/home/user"

执行后,script.log中会新增一行:
[2024-05-20 14:30:00] 执行参数:start backup data /home/user
这就是"$*"的合理用途。

五、总结:一句话记住差异

  • "$@":拆分成多个独立参数,像“一串糖葫芦,每个山楂都是独立的”;
  • "$*":合并成一个整体参数,像“把所有山楂揉成一个丸子”。

日常写Shell脚本时,优先用"$@",既能兼容含空格的参数,又能避免意外的逻辑错误;只有明确需要合并参数时,才用"$*"——这能帮你避开绝大多数参数处理的坑。

若有转载,请标明出处:https://blog.csdn.net/CharlesYuangc/article/details/153048349

http://www.dtcms.com/a/470537.html

相关文章:

  • 重庆网站seo网站外链购买平台
  • 乐清做网站哪家好汕头第一网e京网
  • 为什么ES中不推荐使用wildcard查询
  • 怎么叫人做网站高端的网站推广
  • ICT 数字测试原理 18 - -VCL如何对设备进行预处理
  • 19-基于STM32的人体体征监测系统设计与实现
  • 第12讲:深入理解指针(2)——指针的“安全锁”与“传址魔法”
  • 小企业网站制作wordpress 搭建个人博客
  • 企石镇做网站中国建筑装饰网饶明富
  • 深入洞察:从巴菲特投资哲学萃取最佳实践
  • 设计网站的功能有哪些微营销工具
  • 我的世界做皮肤的网站西安市高新区建设局网站
  • 车载360环视平台:米尔RK3576开发板支持12路低延迟推流
  • 松下机械手焊机气体流量调节
  • x64dbg破解学习(浅尝)
  • RRC状态机:移动通信网络中的连接灵魂
  • LibreCAD 编译详细步骤指南
  • 2025年100道最新软件测试面试题,常见面试题及答案汇总
  • (15)100天python从入门到拿捏《面向对象编程》
  • Spring AI Alibaba 与 Ollama 集成初探:从环境搭建到首次调用
  • 营销型网站的标准网站flash导入页
  • 汉中专业网站建设开发怎么上国外网站
  • Windows上离线安装 PostgreSQL
  • MySQL——表的操作
  • langchain官网翻译:Build a Question/Answering system over SQL data
  • 我的HarmonyOS百宝箱
  • 广州十大室内设计公司排名网站推广seo教程
  • h5网站用什么软件做网站域名备案证书下载
  • 南京本地网站有哪些做网页需要什么
  • 机器学习破解生命之谜:内在无序蛋白质设计迎来革命性突破