侧边栏壁纸
博主头像
张种恩的技术小栈博主等级

行动起来,活在当下

  • 累计撰写 742 篇文章
  • 累计创建 64 个标签
  • 累计收到 39 条评论

目 录CONTENT

文章目录

Linux基础(40)之Shell中的if判断和for循环

zze
zze
2019-10-23 / 0 评论 / 0 点赞 / 622 阅读 / 6660 字

不定期更新相关视频,抖音点击左上角加号后扫一扫右方侧边栏二维码关注我~正在更新《Shell其实很简单》系列

if 语句

if 语句通过关系运算符判断表达式的真假来决定执行哪个分支。Shell 有三种 if ... else 语句:

if ... fi 语句;
if ... else ... fi 语句;
if ... elif ... else ... fi 语句;

if ... else 语句

语法

if [ expression ]
then
   Statement(s) to be executed if expression is true
fi

如果 expression 返回 truethen 后边的语句将会被执行;如果返回 false,不会执行任何语句。最后必须以 fi 来结尾闭合 iffi 就是 if 倒过来拼写,后面也会遇见。

expression 和方括号( [ ])之间必须有空格,否则会有语法错误。

示例

#!/bin/bash
a=10
b=20
if [ $a == $b ]
then
   echo "a is equal to b"
fi
if [ $a != $b ]
then
   echo "a is not equal to b"
fi

运行结果:

a is not equal to b

if ... else ... fi 语句

语法

if [ expression ]
then
   Statement(s) to be executed if expression is true
else
   Statement(s) to be executed if expression is not true
fi

如果 expression 返回 true,那么 then 后边的语句将会被执行;否则,执行 else 后边的语句。

示例

#!/bin/bash
a=10
b=20
if [ $a == $b ]
then
   echo "a is equal to b"
else
   echo "a is not equal to b"
fi

运行结果:

a is not equal to b

if ... elif ... fi 语句

语法

if [ expression 1 ]
then
   Statement(s) to be executed if expression 1 is true
elif [ expression 2 ]
then
   Statement(s) to be executed if expression 2 is true
elif [ expression 3 ]
then
   Statement(s) to be executed if expression 3 is true
else
   Statement(s) to be executed if no expression is true
fi

哪一个 expression 的值为 true,就执行哪个 expression 后面的语句;如果都为 false,那么不执行任何语句。
要注意的是,执行完第一个 expression 的值为 true 的后面的语句后,后面的其它分支中即使 expression 的值为 true 它后面的语句也不执行了。

示例

#!/bin/sh
a=10
b=20
if [ $a == $b ]
then
   echo "a is equal to b"
elif [ $a -gt $b ]
then
   echo "a is greater than b"
elif [ $a -lt $b ]
then
   echo "a is less than b"
else
   echo "None of the condition met"
fi

运行结果:

a is less than b

expression 的写法可参考【Linux基础(26)之bash中的条件测试】。

for循环

for 循环的执行机制是依次将列表中的元素赋值给变量,每次赋值后立即执行一次循环体,直至列表中的元素用尽才结束。
Shell 中 for 循环的语法如下:

for [变量] in [取值列表]
do
    [各种操作]
done

也可使用分号 ; 分割语句写成一行:

for [变量] in [取值列表]; do [各种操作]; done

取值列表有很多类型,大致如下:

枚举值

取值列表可以是枚举的字符串、数值等。
例:

#!/bin/bash
#
for str in 'hello' 'world' '!'
do
    echo $str
done

运行结果:

hello
world
!

glob

取值列表还可以是使用 glob 筛选的文件列表。
例:

#!/bin/bash
#
for file in /etc/*.conf; do
    echo $file
done

运行结果:

[root@localhost tmpsh]# ./for_2.sh 
/etc/asound.conf
/etc/chrony.conf
/etc/dracut.conf
/etc/e2fsck.conf
...

seq

seq 命令能够生成数值列表,这个列表能够被 for 循环迭代。
先了解一下 seq 命令,它的命令格式为:

seq 起始值 [增量] 结束值

不指定增量时默认增量为 1。
例:生成 1-5 之间的数字:

[root@localhost tmpsh]# seq 1 5
1
2
3
4
5

可通过 -w 选项指定生成的数字等长。

下面使用 for 循环迭代一下生成的列表:

#!/bin/bash
#
for num in $(seq 1 5); do
    echo "num:$num"
done

运行结果:

num:1
num:2
num:3
num:4
num:5

{..}

for 循环还支持使用 {<num1>..<num2}> 语法来生成 num1num2 之间的数字列表,相当于使用 seq <num1> <num2>
例:

#!/bin/bash
#
for num in {1..5}; do
    echo "num:$num"
done

运行结果:

num:1
num:2
num:3
num:4
num:5

标准输出流

for 循环可遍历 $(<command>) 的执行结果,前提是 command 的执行结果是输出到标准输出(终端),for 循环回会将标准输出按空格分隔后的每一个单词当作遍历时的变量。
例:

#!/bin/bash
#
for word in $(ls /); do
    echo $word
done

运行结果:

bin
boot
dev
etc
...

文件输入流

for 循环还可通过 $(< <file>) 来接受到文件重定向的输入流来遍历一个文件的每一行以空格分隔的每个单词,例:
例:

#!/bin/bash
#
for line in $(< /etc/passwd); do
    echo $line
done

运行结果:

[root@localhost tmpsh]# ./for_6.sh 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
...

$@

我们已经知道 $@ 可以引用到传入脚本的参数列表,它也可以使用 for 循环来遍历。
例:

# for_7.sh
#!/bin/bash
#
for param in $@; do
    echo $param
done

执行命令 ./for_7.sh 1 5 6,结果:

1
5
6

练习

1、/etc/rc.d/rc3.d 目录下分别有多个以 K 开头和以 S 开头的文件,分别读取每个文件名,以 K 开头的文件输出为文件名加 stop,以 S 开头的文件输出为文件名加 start

#!/bin/bash
#
for line in $(ls /etc/rc.d/rc3.d/ | grep ^[KS]);do
    if echo $line | grep ^K &> /dev/null; then
    	echo "$line stop"
    elif echo $line | grep ^S &> /dev/null; then
        echo "$line start"
    fi 
done

2、写一个脚本,使用 ping 命令探测 192.168.2.1-254 之间的主机的在线状态。

#!/bin/bash
#
for line in 192.168.2.{1..254};do
    if ping -w1 $line &> /dev/null; then
        echo "$line 在线"
    else
        echo "$line 离线"
    fi
done
0

评论区