哎我说老铁们,有没有遇到过这种情况?写了个脚本想传点参数进去,结果要么参数对不上号,要么报错信息看得人一头雾水?别慌,今天咱就唠唠这个让人又爱又恨的shell脚本参数,保准让你听完直拍大腿:"原来这么简单!"
一、参数是啥?怎么往脚本里塞?
咱们先整明白最基础的——参数就是给脚本喂的饲料。举个栗子,你想让脚本批量处理文件,总得告诉它处理哪几个文件吧?这时候参数就派上用场了。比如说有个脚本叫"改名字.sh",你想让它把"照片1.jpg"改成"旅游照001.jpg",就可以这么写:
bash复制./改名字.sh 照片1.jpg 旅游照001.jpg
这里"照片1.jpg"就是第一个参数(1),"旅游照001.jpg"是第二个参数(2)。你看,就跟点菜似的,先点凉菜再点热菜,顺序不能乱。
不过这里有个坑得注意!超过9个参数必须用大括号,比如10,要不然系统会把"10"认成"1后面加个0"[8](@ref)。去年我同事就因为这事折腾一整天,最后发现是把{10}写成了$10,你说冤不冤?
二、特殊符号暗藏玄机
说到参数相关的特殊符号,那真是五花八门。咱们重点唠三个最常用的:
- **#**:跟数钱似的,帮你数数传了几个参数。比如传了5个参数,#就显示5
- $*:把参数打包成个大麻袋,所有参数挤成一团。适合整体处理的时候用
- $@:就像把参数装进分格饭盒,每个参数都保持独立。需要单独处理参数时用它最稳
这俩符号在双引号里表现大不同!比如传了"苹果 香蕉","∗"会变成"苹果香蕉"一个字符串,而"@"会保持"苹果"和"香蕉"两个参数。就跟打包快递似的,前者是塞一个箱子里,后者是分两个小包。
三、高级玩法getopts
想让脚本支持像Linux命令那样的选项参数(比如 -f 文件名)?这时候就得请出getopts这位大神了。举个实际例子,你想让脚本支持 -a(添加)和 -d(删除)功能:
bash复制#!/bin/bash while getopts "a:d:" opt; do case $opt in a) echo "要添加:$OPTARG";; d) echo "要删除:$OPTARG";; ?) echo "输的啥玩意?";; esac done
运行的时候这么写:
bash复制./管理物品.sh -a "新手机" -d "旧键盘"
系统就会自动识别 -a 后面的"新手机"和 -d 后面的"旧键盘"。就跟点奶茶选配料似的,-a是加珍珠,-d是去冰,灵活得很!
四、防坑指南必须看
前几天有个粉丝问我:"为啥我的脚本传参数总报错?"一看代码,好家伙,没做参数校验!这里分享三个保命技巧:
- 参数个数检查:脚本开头加个
if [ $# -lt 2 ]; then echo "至少传俩参数"; exit 1; fi
,比保险柜还靠谱 - 空参数处理:用
${1:-默认值}
语法,参数没传时自动用默认值,避免脚本崩溃 - 危险字符过滤:用
[[ "$1" =~ ^[a-zA-Z0-9_]+$ ]]
这种正则表达式,把特殊字符挡在门外
记得去年有个新闻吗?某公司运维因为脚本没做参数检查,误删了生产数据库。要是当时加了参数校验,哪会出这种幺蛾子?
个人观点时间
要我说啊,参数处理就像炒菜放调料——少了没味儿,多了齁得慌。现在很多新手迷恋各种高级功能,却把基础参数校验给忘了。建议大家养成三个习惯:
- 每个脚本开头先写参数校验,就跟出门检查钥匙似的
- 重要参数加上双引号,比如
"$1"
,防止带空格的参数出问题 - 多用
set -euo pipefail
,让脚本遇到错误立马停下
最后说句掏心窝的话:参数处理看着简单,真要玩转了,你的脚本水平直接上三个台阶!不过可别学某些人,把参数玩出花来却忘了脚本的本来目的,那可就本末倒置喽!