shell编程基础:分支与循环

内容列表

  • 1.分支
    • 1.1 if-then
    • 1.2 if-then-else
    • 1.3 嵌套if
    • 1.4 case
    • 1.5 复合条件测试
  • 2.循环
    • 2.1 for循环
    • 2.2 C风格的for
    • 2.3 for in
    • 2.4 while
    • 2.5 until
  • 3.循环控制
    • 3.1 break
    • 3.2 continue

1. 分支

shell中提供了ifcase进行分支控制,下面将介绍shell中分支使用。

1.1 if-then

命令格式:

# 样式1 
if command
then
  commands
fi
# 样式2,使用;将then写到与if同行
if command; then
  commands
fi

if会判断后面跟着的command的退出状态码,如果返回0,则会执行then后面的commands。
示例:

## 退出状态码为0示例 : 
# 创建if脚本,内容如下
[root@vm14 shell]# cat if.sh 
#!/bin/bash
# 测试if语句
if pwd
then
  echo 'It works'
fi
# 执行if.sh,因为命令pwd成功执行(退出状态码:0),因此then后面的命令被执行
[root@vm14 shell]# sh if.sh 
/root/shell
It works


# 退出状态码非0示例
[root@vm14 shell]# cat if_error.sh 
#!/bin/bash
# 测试一个错误命令
if BadCmd
then
  echo 'It works'
fi
echo 'if finish'
# 运行脚本,因为BadCmd不是一个命令,返回状态码非0,因此then后面的命名未被执行
[root@vm14 shell]# sh if_error.sh 
if_error.sh:行3: BadCmd: 未找到命令
if finish

1.2 if-then-else

命令格式:

# 样式1 
if command
then
  commands
else
  commonds
fi
# 样式2,使用;将then写到与if同行
if command; then
  commands
else
  commonds
fi

if后面的command的退出状态码为0时,执行then后面的commands;非0时,执行else后面的commonds。
示例:

[root@vm14 shell]# cat if_else.sh 
#!/bin/bash
# 测试if-then-else
testuser=root
if grep $testuser /etc/passwd ; then
    echo '第一条命令'
    echo '第二条命令'
    ls -a /root/.b*
else
    echo '没有这个用户!'
fi
[root@vm14 shell]# sh if_else.sh 
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
第一条命令
第二条命令
/root/.bash_history  /root/.bash_logout  /root/.bash_profile  /root/.bashrc

1.3 嵌套if

命令格式:

# 样式1 
if command1
then
  commands
elif command2
then
  commonds
else
  commonds
fi
# 样式2,使用;将then写到与if同行
if command1; then
  commands
elif command2; then
  commands
else
  commonds
fi

示例:

[root@vm14 shell]# cat if_elif.sh 
#!/bin/bash
# 测试嵌套if
var1=5
if [ $var1 -lt 5 ]; then
  echo "$var1 小于5"
elif [ $var1 -eq 5 ]; then
  echo "$var1 等于5"
else
  echo "$var1 大于5"
fi
[root@vm14 shell]# sh if_elif.sh 
5 等于5

1.4 case

命令格式:

case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac

case命令检测变量variable的值,如果是pattern1或pattern2,则执行commands1;如果变量variable是pattern3,则执行commands2;否则执行default commands。
示例:

#!/bin/bash
# 测试case命令,如果第一个参数是start或stop,输出start or stop;
# 如果第一个参数是restart,输出restart;否则输出other
par=$1
case $par in 
start | stop ) echo 'start or stop';;
restart ) echo 'restart' ;;
*) echo 'other' ;;
esac

# 当第一个参数是start时,输出start or stop
[root@vm14 shell]# sh case.sh start
start or stop
# 第一个参数是restart时,输出restart
[root@vm14 shell]# sh case.sh restart
restart
# 第一个参数是hello,输出other
[root@vm14 shell]# sh case.sh hello
other

1.5 复合条件测试

命令格式:

[ condition1 ] && [ condition2 ] 
[ condition1 ] || [ condition2 ]

2. 循环

bash shell中的循环包括forwhileuntil,下面将分别介绍他们。

2.1 for循环

命令格式:

# 样式1 
for var in list
do
  commands
done
# 样式2,使用;将do写到与for同行
for var in list; do
  commands
done

示例:

#@@@@@ 示例1,当编程语言有空格时,用双引号进行处理,否则会当两个名称处理
[root@vm14 shell13]# cat for.sh 
#!/bin/bash
# for命令测试
for name in java "bash shell"
do
    echo 编程语言:$name
done
echo 命令结束后name会保存最后一个语言:$name
[root@vm14 shell13]# sh for.sh 
编程语言:java
编程语言:bash shell
命令结束后name会保存最后一个语言:bash shell


#@@@@@ 示例2,变量中的空格处理
[root@vm14 shell13]# cat for_space.sh 
#!/bin/bash
# 变量中空格处理
echo 切分异常情况:
str="java 'bash shell'"
for s in $str; do
  echo $s
done
echo 方式1,使用eval:
eval "for s in $str; do echo \$s; done"
echo 方式2,使用数组:
arr=(java "bash shell")
for name in "${arr[@]}"; do
  echo $name
done
[root@vm14 shell13]# sh for_space.sh 
切分异常情况:
java
'bash
shell'
方式1,使用eval:
java
bash shell
方式2,使用数组:
java
bash shell


#@@@@@ 示例3 从命令中取值
# 创建names文件,存放待读取数据
[root@vm14 shell13]# cat names
java
bash shell
# 读取names文件中的数据,并循环输出
[root@vm14 shell13]# cat for_cmd.sh 
#!/bin/bash
# for从命令中取值测试
file=names
# 使用默认IFS(internal field separator):空格、制表符、换行符
for name in $(cat $file);do
    echo 默认IFS:$name
done

# 修改IFS,仅使用换行符
IFS_OLD=$IFS # 存储原IFS
IFS=$'\n'
for name in $(cat $file); do
    echo 换行符IFS:$name
done
IFS=$IFS_OLD # 恢复IFS
[root@vm14 shell13]# sh for_cmd.sh 
默认IFS:java
默认IFS:bash
默认IFS:shell
换行符IFS:java
换行符IFS:bash shell


#@@@@@ 示例4,使用通配符读取文件列表
[root@vm14 shell13]# cat for_dir.sh 
#!/bin/bash
# 使用通配符读取目录下文件,可以传递多个通配符 
for file in /home/* /root/*cfg
do
  if [ -d "$file" ];then
    echo "$file 是目录"
  elif [ -f "$file" ];then
    echo "$file 是文件"
  fi
done

[root@vm14 shell13]# sh for_dir.sh 
/home/dft 是目录
/home/test1 是目录
/home/test2 是目录
/root/anaconda-ks.cfg 是文件

2.2 C风格的for

C语言风格的for循环与bash shell差异点:

  • 变量赋值可以有空格;
  • 条件中的变量不以美元符开头;
  • 迭代过程的算式未用expr命令格式。

命令格式:

# 样式1 
for (( variable assignment ; condition ; iteration process ))
do
  commands
done
# 样式2,使用;将do写到与for同行
for (( variable assignment ; condition ; iteration process )); do
  commands
done

示例:

#@@@@@ 示例1,通过for循环输出0-9
[root@vm14 shell13]# cat cfor.sh 
#!/bin/bash
# 测试C风格for循环
for (( a=0; a<10 ;a++ ))
do
  echo 当前数字$a
done
[root@vm14 shell13]# sh cfor.sh 
当前数字0
当前数字1
当前数字2
当前数字3
当前数字4
当前数字5
当前数字6
当前数字7
当前数字8
当前数字9


# @@@@@ 示例2,多变量for循环
[root@vm14 shell13]# cat cfor2.sh 
#!/bin/bash
# 测试C风格for循环
for (( a=0,b=9; a<10 ;a++,b-- ))
do
  echo 当前数字a:$a , b:$b
done
[root@vm14 shell13]# sh cfor2.sh 
当前数字a:0 , b:9
当前数字a:1 , b:8
当前数字a:2 , b:7
当前数字a:3 , b:6
当前数字a:4 , b:5
当前数字a:5 , b:4
当前数字a:6 , b:3
当前数字a:7 , b:2
当前数字a:8 , b:1
当前数字a:9 , b:0

2.3 for in

[root@an01 ~]# cat forin.sh 
for i in {1..10} 
do
  echo $i
done
[root@an01 ~]# sh forin.sh 
1
2
3
4
5
6
7
8
9
10

2.4 while

while: 循环检测测试条件的状态码,如果为0,则执行do-done间命令,否则退出循环。
命令格式:

# 样式1 
while test command
do
  other commands
done
# 样式2,使用;将do写到与while同行
while test command; do
  other commands
done

示例:

#@@@@@ 示例1,当变量var1大于0时,输出$var1,并进行减一操作
[root@vm14 shell13]# cat while.sh 
#!/bin/bash
# 测试while命令
var1=10
while [ $var1 -gt 0 ]; do
  echo $var1
  var1=$[$var1-1]
done
[root@vm14 shell13]# sh while.sh 
10
9
8
7
6
5
4
3
2
1

#@@@@@ 示例2, 当while后有多个命令时,以最后一个命令的退出状态码为退出循环条件
[root@vm14 shell13]# cat while2.sh 
#!/bin/bash
# 测试while命令
var1=5
while echo $var1 ; [ $var1 -gt 0 ]; do
  echo "in loop"
  var1=$[$var1-1]
done
[root@vm14 shell13]# sh while2.sh 
5
in loop
4
in loop
3
in loop
2
in loop
1
in loop
0

2.5 until

until命令和while命令工作的方式完全相反。 until命令要求你指定一个通常返回非零退出状态码的测试命令。
命令格式:

# 样式1 
until test commands
do
  other commands
done
# 样式2,使用;将do写到与until同行
until test commands; do
  other commands
done

示例:

#@@@@@ 示例1,一直对var1进行减25操作,直到var1等于0为止
[root@vm14 shell13]# cat until.sh 
#!/bin/bash
# until命令测试
var1=100
until [ $var1 -eq 0 ]; do
  echo $var1
  var1=$[$var1-25]
done
[root@vm14 shell13]# sh until.sh 
100
75
50
25

## untul有多个测试命令时,只有在最后一个命令成立时停止

3. 循环控制

bash shell提供了breakcontinue两个命令来跳出循环,break为跳出循环,continue为跳出本次循环。

3.1 break

示例:

#@@@@@ 示例1,使用break跳出for循环 
[root@vm14 shell13]# cat break.sh 
#!/bin/bash
# 使用break跳出for循环 
for var1 in 1 2 3 4 5 6 7 8 9 10; do
  if [ $var1 -eq 5 ]; then
    break
  fi
  echo "当前数字: $var1"
done
echo "循环结束"
[root@vm14 shell13]# sh break.sh 
当前数字: 1
当前数字: 2
当前数字: 3
当前数字: 4
循环结束


#@@@@@ 示例2,使用break跳出外层循环
[root@vm14 shell13]# cat break2.sh 
#!/bin/bash
# 使用break跳出外循环 
for (( a=0;a<100;a++ ));do
  echo 外循环a:$a
  for ((b=0;b<10;b++));do
    if [ $b -gt 2 ]; then
      # break n
      # 其中n指定了要跳出的循环层级。默认情况下, n为1,表明跳出的是当前的循环。
      # 如果你将n设为2, break命令就会停止下一级的外部循环。
      break 2
    fi
    echo 内循环b:$b
  done
done
echo "循环结束"
[root@vm14 shell13]# sh break2.sh 
外循环a:0
内循环b:0
内循环b:1
内循环b:2
循环结束

3.2 continue

示例:

#@@@@@ 示例1,如果$va1大于2且小于8,则中断本次循环
[root@vm14 shell13]# cat continue.sh 
#!/bin/bash
# 使用continue跳出本次for循环 
for var1 in 1 2 3 4 5 6 7 8 9 10; do
  if [ $var1 -gt 2 ] && [ $var1 -lt 8 ]; then
    continue
  fi
  echo "当前数字: $var1"
done
echo "循环结束"
[root@vm14 shell13]# sh continue.sh 
当前数字: 1
当前数字: 2
当前数字: 8
当前数字: 9
当前数字: 10
循环结束


#@@@@@ 示例2,中断外层循环
[root@vm14 shell13]# cat continue2.sh 
#!/bin/bash
# 使用break跳出外循环 
for (( a=0;a<5;a++ ));do
  echo 外循环a:$a
  for ((b=0;b<2;b++));do
    if [ $a -gt 2 ]; then
      # continue n
      # 其中n指定了要跳出的循环层级。默认情况下, n为1,表明跳出的是当前的循环。
      # 如果你将n设为2,continue命令就会停止下一级的本次外部循环。
      continue 2
    fi
    echo 内循环b:$b
  done
done
echo "循环结束"
[root@vm14 shell13]# sh continue2.sh 
外循环a:0
内循环b:0
内循环b:1
外循环a:1
内循环b:0
内循环b:1
外循环a:2
内循环b:0
内循环b:1
外循环a:3
外循环a:4
循环结束


你可能感兴趣的:(linux)