1. 使用read命令来接受输入

使用read来把输入值分配给一个或多个shell变量,read从标准输入中读取值,给每个单词分配一个变量,所有剩余单词都被分配给最后一个变量,如果变量名没有指定,默认标准输入的值赋值给系统内置变量REPLY

read [options] [name ...]

#常见选项
-p  	  #指定要显示的提示
-s 		  #静默输入,一般用于密码
-n N      #指定输入的字符长度N
-d 'CHAR'   #输入结束符
-t N      #TIMEOUT为N秒

2. 按生效范围划分两类

  1. 配置文件分类

  • 按生效范围:分为全局配置(如/etc/profile/etc/bashrc等,对所有用户有效)和个人配置(如~/.bash_profile~/.bashrc等,仅对特定用户有效)

  • 按 shell 登录方式:主要关注交互式登录场景(直接输入账号密码登录或使用su - UserName切换用户)

  1. 交互式登录时配置文件的执行特点

  • 执行顺序受文件之间的调用关系影响,同一文件在不同位置可能被多次执行(如示例中/etc/bashrc执行了两次)

  • 在文件最前面添加内容时,执行顺序大致为:/etc/profile/etc/bashrc/etc/bashrc

  • 在文件最后面添加内容时,执行顺序大致为:/etc/bashrc/etc/profile/etc/bashrc

  1. 重要注意事项

  • 配置文件的执行顺序不是简单的线性顺序,而是由文件之间的相互调用关系决定

  • 同一份配置文件可能会被多次执行,因此在编写配置时要注意避免重复定义或冲突

  • 修改配置文件后,通常需要重新登录才能使配置生效

3. 选择执行 if 语句

格式:

if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else 
COMMANDS; ] fi

单分支

if 判断条件;then
   条件为真的分支代码
fi
str1=def;
if [ $str1 = "abc" ];then 
 echo "str1 is abc";
fi

双分支

if 判断条件; then
条件为真的分支代码
else
条件为假的分支代码
fi
str1=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
以上条件都为假的分支代码
fi
str=$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";
fi

4. 条件判断 case 语句

格式:

case WORD in [PATTERN [| PATTERN]...) COMMANDS ;;]... esac
case 变量引用 in
PAT1)
分支1
 ;;
PAT2)
分支2
 ;;
...
*)
默认分支
 ;;
esac

case支持glob风格的通配符:

*     #任意长度任意字符
?     #任意单个字符
[]    #指定范围内的任意单个字符
|     #或者,a|b

5. 循环 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
  循环体
done

7. 关于 () 和 {}


 ( ( 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 之后则为真, > 要转义