Shell脚本
1. 使用read命令来接受输入
使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量,如果变量名没有指定,默认标准输入的值赋值给系统内置变量REPLY
read [options] [name ...]
#常见选项
-p #指定要显示的提示
-s #静默输入,一般用于密码
-n N #指定输入的字符长度N
-d 'CHAR' #输入结束符
-t N #TIMEOUT为N秒2. 按生效范围划分两类
配置文件分类
按生效范围:分为全局配置(如
/etc/profile、/etc/bashrc等,对所有用户有效)和个人配置(如~/.bash_profile、~/.bashrc等,仅对特定用户有效)按 shell 登录方式:主要关注交互式登录场景(直接输入账号密码登录或使用
su - UserName切换用户)
交互式登录时配置文件的执行特点
执行顺序受文件之间的调用关系影响,同一文件在不同位置可能被多次执行(如示例中
/etc/bashrc执行了两次)在文件最前面添加内容时,执行顺序大致为:
/etc/profile→/etc/bashrc→/etc/bashrc在文件最后面添加内容时,执行顺序大致为:
/etc/bashrc→/etc/profile→/etc/bashrc
重要注意事项
配置文件的执行顺序不是简单的线性顺序,而是由文件之间的相互调用关系决定
同一份配置文件可能会被多次执行,因此在编写配置时要注意避免重复定义或冲突
修改配置文件后,通常需要重新登录才能使配置生效
3. 选择执行 if 语句
格式:
if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else
COMMANDS; ] fi单分支
if 判断条件;then
条件为真的分支代码
fistr1=def;
if [ $str1 = "abc" ];then
echo "str1 is abc";
fi双分支
if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fistr1=def;
if [ $str1 = "abc" ];then
echo "str1 is abc";
else
echo "str1 is not abc"
fi多分支
if 判断条件1; then
条件1为真的分支代码
elif 判断条件2; then
条件2为真的分支代码
elif 判断条件3; then
条件3为真的分支代码
...
else
以上条件都为假的分支代码
fistr=$1;
if [ "$str" = "abc" ]; then
echo "is abc";
elif [ "$str" = "def" ]; then
echo "is def";
elif [ "$str" = "xyz" ]; then
echo "is xyz";
else
echo "not abc,not def"
fi说明:
多个条件时,逐个条件进行判断,第一次遇为“真”条件时,执行其分支,而后结束整个if语句
if 语句可嵌套
str1=$1
str2=$2
if [ "$str1" = "abc" ];then
echo "str1 is abc";
if [ "$str2" = "def" ];then
echo "str2 is def";
fi
else
echo "str1 is not abc";
fi4. 条件判断 case 语句
格式:
case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esaccase 变量引用 in
PAT1)
分支1
;;
PAT2)
分支2
;;
...
*)
默认分支
;;
esaccase支持glob风格的通配符:
* #任意长度任意字符
? #任意单个字符
[] #指定范围内的任意单个字符
| #或者,a|b5. 循环 for
格式1:
for NAME [in WORDS ... ] ; do COMMANDS; done
#方式1
for 变量名 in 列表;do
循环体
done
#方式2
for 变量名 in 列表
do
循环体
done
执行机制:依次将列表中的元素赋值给“变量名”; 每次赋值后即执行一次循环体; 直到列表中的元素耗尽,循环结束
如果省略 [in WORDS ... ] ,此时使用位置参数变量 in "$@"
for 循环列表生成方式:
直接给出列表
整数列表:如 {start..end}
返回列表的命令:如 $(COMMAND)
使用glob,如:*.sh
变量引用,如:$@,$,$#
6. 循环 while
格式:
while CONDITION; do COMMANDS; done
while CONDITION; do
循环体
done
while CONDITION
do
循环体
done7. 关于 () 和 {}
( ( cmd1;cmd2;... ) 和 { cmd1;cmd2;...; } 都可以将多个命令组合在一起,批量执行
( list ) 会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境
{ list; } 不会开启子shell, 在当前shell中运行,会影响当前shell环境,左侧要有空格,右侧要有; 结束8. 条件测试命令
8.1. 条件测试命令
test expr
[ arg... ] #同 test
[[ expression ]] #增加版的[],支持[],支持扩展正则表达式和通配符注意:[] 中的表达式,前后要有空格
8.2. 数学相关
#数字相关 格式 arg1 OP arg2
-eq #等于
-ne #不等于
-lt #小于
-le #小于等于
-gt #大于
-ge #大于等于
#算术表达式比较
== #相等
!= #不相等
<= #小于或等于
= #大于或等于
< #小于
> #大于8.3. 文件判断相关
-a FILE #如果文件存在则为真
-b FILE #如果文件为块特殊文件则为真
-c FILE #如果文件为字符特殊文件则为真
-d FILE #如果文件为目录则为真
-e FILE #如果文件存在则为真
-f FILE #如果文件存在且为常规文件则为真
-g FILE #如果文件的组属性设置打开则为真
-h FILE #如果文件为符号链接则为真
-L FILE #如果文件为符号链接则为真
-k FILE #如果文件的粘滞 (sticky) 位设定则为真
-p FILE #如果文件为命名管道则为真
-r FILE #如果当前用户对文件有可读权限为真
-s FILE #如果文件存在且不为空则为真
-S FILE #如果文件是套接字则为真
-t FD #如果文件描述符在一个终端上打开则为真
-u FILE #如果文件设置了SUID特殊权限则为真
-w FILE #如果当前用户对文件有可写权限为真
-x FILE #如果当前用户对文件有可执行权限为真
-O FILE #如果当前用户是文件属主为真
-G FILE #如果当前用户对文件属组为真
-N FILE #如果文件上次被读取之后修改过则为真
FILE1 -nt FILE2 #如果 file1 文件新于 file2 文件 则为真(根据修改日期)
FILE1 -ot FILE2 #如果 file1 文件旧于 file2 文件则为真
FILE1 -ef FILE2 #如果 file1 文件是 file2 文件的硬链接则为真8.4. 字符串判断相关
-z STRING #判断字符串是否为空,为空则为真
-n STRING #如果字符串不为空则为真
STRING #同上
#两个字符串变量比较,一定要有空格,如果没有空格,就变成赋值了
STRING1 = STRING2 #如果 string1 和 string2 字符串相同则为真
STRING1 != STRING2 #如果 string1 和 string2 字符串不相同则为真
STRING1 < STRING2 #只比较第一个字符,以字母表顺序来比较,string1在string2 之前则为真,< 要转义
STRING1 > STRING2 #只比较第一个字符,以字母表顺序来比较,string1在string2 之后则为真, > 要转义