shell 编程(6) 之结构化控制

发布时间 2023-03-30 16:17:01作者: by1314

for 循环

列表中的值出现特殊符号时,使用引号将其括起来,以免出现歧义。当列表的值出现引号空格时,就会出现歧义

语法:
for <VARIABLE> in <LIST>
do
<COMMAND>....
done 

1. 从变量中读取列表值

#!/bin/bash/
city="China Japan Rassia"
for i in $city
do
echo "I'm from $i"
done

2. 从命令中取值

#!/bin/bash/
file=cityname
for i in $(cat $file)
do
echo "I'm from $i"
done
 * IFS 系统默认环境变量

更改输出情况,IFS 变量叫做内部字段分隔符,有三种形式制表符、换行符、空格
IFS=$'\n'

ps:在处理代码量较大的脚本时,可能在一个地方需要修改 IFS 的值,然后再忽略这次修改,在脚本的其他地方继续沿用 IFS 的默认值。一个可参考的安全实践是在改变 IFS 之前保存原来的 IFS 值,之后再恢复它,方法如下:

IFS.OLD=$IFS
IFS=$'\n'              #在代码中使用新的 IFS 值
IFS=$IFS.OLD           #这里可以参考一下利用**中间的变量**进行值互换

这就保证了在脚本的后续操作中使用的是 IFS 的默认值。如果要指定多个 IFS 字符,只要将它们在赋值行串起来就行,如下所示:
IFS=$'\n':;" #赋值会将换行符、冒号、分号和双引号作为字段分隔符

3. 使用通配符读取目录

#!/bin/bash
for file in 路径/*
do
  if [ -d "$file" ]
  then
    echo "$file is a directory "
  elif [ -f "$file" ]
  then 
    echo "$file is a file"
  fi
done

ps:1)这里注意[]的前后空格
2)if 语句判断$file 变量的类型,当类型为“-d”时,即读取到的 路径/* 内容为目录时,输出此条目为目录,
3)当类型为“-f”时,即读取到的 路径/* 内容为文件时,输出此条目为文件
4)在 Linux 中,目录名和文件名中包含空格是合法的。对于这种情况,应该将 $file 变量用双引号引起来。如果不这么做,遇到含有空格的目录名或文件名时就会有错误产生

if 语句

1. if-then

语法如下:

if command
then
  commands
fi

ps:fi 是结束标志。

例:当ls命令执行成功,输出sucess

if ls
then
  echo "sucess"
fi
条件比较

语法如下:

if test condition
then
 commands
fi

ps:当test 命令后 condition 为空,它会以非零的退出状态码退出,并执行 else 语句块

  • bash 用于整数的比较
运算符 含义 示例
-eq 等于 [ "$a" -eq "$b" ]
-ne 不等于 [ "$a" -ne "$b" ]
-gt 大于 [ "$a" -gt "$b" ]
-ge 大于等于 [ "$a" -ge "$b" ]
-lt 小于 [ "$a" -lt "$b" ]
-le 小于等于 [ "$a" -le "$b" ]
  • bash 字符串的比较(使用二进制运算符)
运算符 含义 示例
= 等于 [ "$a" = "$b" ]
!= 不等于 [ "$a" != "$b" ]
== 等于 [ "$a" == "$b" ]
  • bash 测试运算符
运算符 含义 示例
-b 文件存在并且是块特殊 [ -b <FILE> ]
-c 文件存在并且是字符特殊 [ -c <FILE> ]
-d 文件存在并且是目录 [ -d <DIRECTORY> ]
-e 文件存在 [ -e <FILE> ]
-f 文件是常规文件 [ -f <FILE> ]
-L 文件存在并且是符号链接 [ -L <FILE> ]
-r 文件存在并且授予了读权限 [ -r <FILE> ]
-s 文件存在并且大小大于零 [ -s <FILE> ]
-w 文件存在并且授予了写权限 [ -w <FILE> ]
-x 文件存在并且授予了执行权限 [ -x <FILE> ]
-nt 前者比后者修改时间晚 [ <FILE1> -nt <FILE2> ]
-ot 前者比后者修改时间早 [ <FILE1> -ot <FILE2> ]
  • bash 逻辑运算符
运算符 含义 示例
|| [2 -gt 1]
&& [2 -gt 1] && [1 -gt 2];echo $?

ps:$? 输出为0则成功

2. if-then-else

语法如下:

if command
then
  commands
else
  commands
fi

3. if-then-elif-then-else

语法如下:

if command
then
  commands
elif
  command
then
  commands
else
  commands
fi

4. if 嵌套语句

语法如下:

if command
  then
  commands
else
  commands
  if command
  then
     commands
  fi
fi

while 语句

语法如下:

while test command
do
 other commands
done

while 命令的关键在于所指定的 test command 的退出状态码必须随着循环中运行的命令而改变

#!/bin/bash
i=5
while [ $i -gt 0 ]
do 
  echo $i
  i =$[ $i-1 ]
done

ps:在 while 语句中,可以在 while 命令后放入多个测试命令,只有最后一个命令的退出代码决定了 Bash Shell 是否执行已定义的 other commands。需要注意的是,每一个测试条件都要放在单独的一行中

until 语句

until test commands
do
  other commands
done

和 while 语句一样,也可以在 until 语句后放入多个测试令,也是只有最后一个命令的退出代码决定了时候执行已定义的 other commands。

case 条件语句

适用于:子句太多的情况
语法:

case value in 
  pattern1)
    commands
    ;;
  pattern2)
    commands
    ;;
esac

说明:case语句尝试顺序逐个将value和每个pattern,想在 case 语句中使用到类似于 else 子句的结构语句,可以在 case 语句中使用 * 作为最终模式。

#!/bin/bash
case $USER in
  redhat | jack)
    echo "welcom,$USER"
    ;;
  test)
    echo "the test user account"
    ;;  
  *)
     echo "Sorry"
    ;;
esac

对于多模式操作,我们可以合并模式来共享一个操作模块,这里使用管道字符 | 来分割多个模式

嵌套循环

对于 shell 而言,它能够区分内部 for 循环和外部 while 循环各自的 do 和 done 命令
例如:

for ((a = 1;a<=3;a++))
do
  echo "starting loop $a:"
  for ((b=1;b<=3;b++))
  do
    echo " inside loop :$b"
  done
done

控制循环两个命令

break 和 continue 能够帮我们控制循环的内部情况

break 命令

使用 break 可以退出任意类型的循环

#!/bin/bash

i=1
while [$i -lt 10]
do
  if [$i -eq 5]
  then
    break
  fi
  echo "Iteration:$i"
  i=$[ $i+1 ] 
done
echo "while completed"
  • break n 命令
    • n 指定了要跳出循环的层级,n=1 是跳出当前的循环,终止第 n 级的外部循环

continue 命令

continue 命令可以提前终止循环

  • continue n 命令
    • continue n 默认 n=1,如果没有 n 表示跳过本次循环,进入下一次循环


输出结果如下

ps:注意使用continue时,这里外部循环依然继续