来自AI助手的总结
介绍Shell特殊变量、参数展开与脚本参数处理技巧

一、位置参数是命令行和脚本之间的桥梁
这里将位置参数列为 Shell 编程核心内容,最常见的是下面几个:
$1、$2、$3:脚本的第 1、2、3 个参数$0:脚本本身的名字$#:脚本参数个数$@:所有参数$*:所有参数
最基础的演示脚本如下:
#!/bin/bash
echo "脚本第1个参数:$1"
echo "脚本第2个参数:$2"
echo "脚本参数数量:$#"
执行效果:
bash /server/scripts/devops-shell/02.vars.sh a b c d e
二、位置参数最常见的使用场景
2.1 接收用户名并做检查
例如执行脚本时传入用户名,然后用 id 判断用户是否存在:
bash /server/scripts/devops-shell/03.check_user.sh zq
这种写法很适合做:
- 用户检查
- 服务管理脚本
- 发布脚本参数传递
- 巡检脚本指定主机或目录
2.2 输出脚本帮助
$0 非常适合用来打印使用方法:
#!/bin/bash
echo "Usage: $0 {start|stop|restart}"
2.3 检查参数个数
$# 最常与判断结合:
if [ $# -ne 1 ]; then
echo "Help: $0 {start|stop|restart}"
exit 6
fi
三、$10 为什么会出问题
这是这里专门强调的面试题:
$10在 Shell 里会被解释成$1加上字符0- 参数位数大于 9 时,应写成
${10}、${11}
例如:
echo $1 $2 $3 $4 $5 $10 $11
echo $1 $2 $3 $4 $5 ${10} ${11}
四、$@ 和 $* 的区别要看双引号
不加双引号时,$@ 和 $* 看起来差别不大;真正的差异出现在加上双引号之后。
set -- "I am oldboy" teacher lidao
for i in "$*"; do echo "$i"; done
for j in "$@"; do echo "$j"; done
结果是:
"$*"会把所有参数合并成一个整体"$@"会保留每个参数的边界
因此,只要你打算在循环或函数中逐个处理参数,优先用 "$@"。
五、状态变量用于判断命令有没有执行成功
这里列出的状态类特殊变量包括:
$?:上一个命令或脚本的返回值,0表示成功$$:当前脚本的 PID$!:上一个后台命令的 PID$_:上一个命令的最后一个参数
其中最常用的还是 $?。
5.1 实战:输入命令并检查执行结果
#!/bin/bash
cmd="$@"
$cmd &>/dev/null
if [ $? -eq 0 ]; then
echo "$cmd 运行成功"
else
echo "$cmd 运行失败"
fi
调用示例:
bash /server/scripts/devops-shell/07.check_cmd.sh ls -a
六、参数展开让变量处理更高效
这里将参数展开分成几类:长度统计、删除、截取和替换。
6.1 统计长度
oldboy="lidao996"
echo ${#oldboy}
6.2 删除左边或右边的内容
var=oldboylidao996
echo ${var#oldboy}
echo ${var##*o}
dir=/etc/sysconfig/network-scripts/ifcfg-eth0
echo ${dir##*/}
echo ${dir%/*}
这个技巧很适合:
- 提取文件名
- 提取目录名
- 删除固定前后缀
6.3 截取变量
var=oldboy
echo ${var:3}
echo ${var:1:3}
6.4 替换变量内容
var=oldboylidao996
echo ${var/o/-}
echo ${var//o/-}
七、实战:统计句子里长度不超过 6 的单词
Shell 版本示例如下:
#!/bin/bash
hua="I am oldboy teacher welcome to oldboy training class."
hua_del=$(echo "$hua" | sed 's#\.##g')
for word in ${hua_del}; do
if [ ${#word} -le 6 ]; then
echo "单词字符数小于等于6: ${word}"
fi
done
同样的需求也可以用 awk 一条命令完成,这也说明参数展开和三剑客是可以互相替补的。
八、默认值扩展适合给变量兜底
这里列出的 4 种常见写法如下:
${parameter:-word}:变量未定义或为空时,输出默认值,但不改变量本身${parameter:=word}:变量未定义或为空时,赋默认值并写回变量${parameter:?word}:变量未定义或为空时,输出错误信息${parameter:+word}:变量存在且非空时,用word替换输出
例如:
echo ${name:-root}
echo ${lidao:=996}
echo ${name:+root}
其中最常用的是 :- 和 :=,非常适合给脚本参数、目录变量、服务名变量设置保底值。
九、变量赋值方式有哪些
这里将变量赋值分成 5 种常见来源:
- 直接赋值:
oldboy=lidao996 - 命令结果赋值:
hostname=$(hostname) - 脚本传参赋值:
user_name=$1 read交互赋值- 从文件读取内容赋值
其中 read 是交互脚本里必须掌握的。
9.1 read 常用参数
-p:提示信息-t:超时退出-s:不显示输入内容,适合密码输入
示例:
read -p "请输入2个数字num1 num2:" num1 num2
read -s -p "请输入密码:" pass
十、实战:用户输入密码后倒序输出
示例脚本如下:
#!/bin/bash
read -s -p "请输入密码:" pass
echo
pass_rev=$(echo "$pass" | rev)
echo "正在猜测你的密码....."
echo "马上破解成功"
echo "$pass_rev"
echo "看看对不对?"
这个例子虽然简单,但正好把 read -s、命令替换、变量输出串起来了。
十一、写参数处理脚本时的推荐顺序
把这里的内容合起来,日常写脚本时可以遵循这个顺序:
1、用 $# 检查参数个数。
2、用 $0 输出帮助信息。
3、用 ${1:-default} 给参数设置默认值。
4、用 $? 检查关键命令是否成功。
5、用 read 补充必须的交互输入。
按这个套路写,脚本的参数入口会清晰很多,也更不容易因为输入异常而出错。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END







暂无评论内容