shell支持loop吗_shell script 循环(loop)

shell script 循环(loop)

除了if...then...fi这种条件判断式之外,循环可能是程序当中最重要的一环了。循环可以不断执行某个程序段落,直到用户设置的条件达成为止,所以重点是那个“条件的达成”是什么。除了这种依据判断式达成与否的不定循环之外,还有另外一种已经固定要跑多少次的循环,可称为固定循环。

while do done和until do done(不定循环)

一般来说,不定循环最常见的就是下面这两种状态了。

while [ condition ] //中括号内的条件就是判断式

do //是循环的开始

程序字段 //循环的内容

done //是循环的结束

while的中文是“当......时,在......期间”,所以,这种方式说的是当condition条件成立时,就进行循环,直到condition的条件不成立才停止的意思。

还有另外一种不定循环的方式

until [ condition ]

do

程序字段

done

这种方式恰恰与while相反,他说的是当conditiong条件成立时,就终止循环,否则就继续执行循环的程序段。

我们以while来做一个简单的练习,假设我要让用户输入yes或者是YES才结束程序的执行,否则就一直进行告知用户输入合法的字符串。

脚本sh13.sh内容

#!/bin/bash

#Program

#    Repeat question until user input correct answer.

#History:

#2015/06/19 Awake First release

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH

while [ "$yn" != "yes" -a "$yn" != "YES" ] //(当condition条件成立时,就进行循环,直到condition的条件不成立才停止程序)$yn即不等于yes也不等于YES,那么就进入循环吧,如果等于就不进入循环

do //进入循环

read -p "Please input yes/YES to stop this program: " yn //循环的是什么呢?就是这条语句,提示用户输入变量内容,如果输入不正确就循环

done //如果输入正确的字符也就是condition的条件不成立了,那么停止程序

echo "OK! you input the correct answer."

上面这个例题说明的是当$yn这个变量不是yes且$yn也不是YES时,才进入循环内的程序,而如果$yn是yes或YES时,就会离开循环。

[root@awake scripts]# ./sh13.sh

Please input yes/YES to stop this program:yes //输入正确的参数

you input the correct answer.

[root@awake scripts]# ./sh13.sh

Please input yes/YES to stop this program:YES //输入正确的参数

you input the correct answer.

[root@awake scripts]# ./sh13.sh

Please input yes/YES to stop this program:yy

Please input yes/YES to stop this program:^C

上面的例子如果用until,它的条件会变成这样

脚本sh13-2.sh内容

[root@awake scripts]# more sh13-2.sh

#!/bin/bash

#Program

# Repeat question until user input correct answer.

#History:

#2015/06/19 Awake First release

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH

until [ "$yn" == "yes" -o "$yn" == "YES" ] //(当conditiong条件成立时,就终止循环,否则就继续执行循环的程序段)当$yn变量内容等于yes或YES时,那么就终止循环,否则就循环

do

read -p "Please input yes/YES to stop this program:" yn

done

echo "OK! you input the correct answer."

[root@awake scripts]#

如果要计算1+2+3...+100这个数值,利用循环是这样的

脚本sh14.sh内容

#!/bin/bash

#program

# use loop to calculate "1+2+3...+100" result

#History:

#2015/06/19 Awake First release

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH

s=0 //定义s的变量值为0(这是累加的数值变量)

i=0 //定义i的变量值为0(这是累计的数值,亦即是1,2,3....)

while [ "$i" != "100" ] //(当condition条件成立时,就进行下面的循环,直到condition的条件不成立才停止程序,此例到100就不成立了)也就是$i的数值会循环范围是1-99

do

i=$(($i+1)) //这个变量的定义感觉是覆盖了前面的i=0的变量,$i变量每次都会增加1,$i会从1变到99,也就是加99次,这个值会从1-100;

s=$(($s+$i)) //小括号重点的$s的值是0,并不会循环,这个值是0+1一次,然后是0+2一次,一直到100。

done

echo "The result of '1+2+3...+100' is == $s" 那么此处$s的结果就是5050了。

脚本sh14.sh的执行情况

[root@awake scripts]# ./sh14.sh

The result of '1+2+3...+100' is == 5050

[root@awake scripts]#

如果想要用户自行输入一个数字,让程序有1+2+...直到你输入数字为止,该如何编写?

脚本sh14-2.sh内容

#!/bin/bash

#program

# use loop to calculate "1+2+3...+100" result

#History:

#2015/06/19 Awake First release

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH

s=0 //定义s的变量值为0(这是累加的数值变量)

i=0 //定义i的变量值为0(这是累计的数值,亦即是1,2,3....)

read -p "Use loop to calculate link 1+2+3... input you digit:" n

while [ "$i" != "$n" ] //(当condition条件成立时,就进行下面的循环,直到condition的条件不成立才停止程序,此例到100就不成立了)也就是$i的数值会循环范围是1-99

do

i=$(($i+1)) //这个变量的定义感觉是覆盖了前面的i=0的变量,$i变量每次都会增加1,$i会从1变到99,也就是加99次,这个值又加了1, 会从1-100;

s=$(($s+$i)) //小括号重点的$s的值是0,并不会循环,这个值是0+1一次,然后是0+2一次,一直到100。

done

echo "The result of '1+2+3...+100' is == $s" 那么此处$s的结果就是5050了。

shell脚本对变量类型没有限制,你输入数字,phone就可以直接当数值型来用。

只是这里的判断表达式中不支持直接正则匹配,你要用grep, sed, awk这些支持正则的工具才行,然后用 $? 取得执行状态来判断是否匹配成功。

read -p "Phone Number (xxxxxxxx):" phone

echo "$n" | egrep "^[0-9]{8}$" >/dev/null //查看用户输入的是否为8位数字,如果不是数字,那么将错误信息输入到null//

if [ $? -eq 0 ]; then //判断$?是否为0 如果为0那么向下执行

echo ....

我想做一个实例是限制用户的输入内容是数字,不可以是其他,不限制位数,怎么做?

for...do...done(固定循环)

相对于while,until的循环方式是必须要“符合某个条件”的状态,for这种语法则是“已经知道要进行几次循环”的状态,他的语法是:

for var in con1 con2 con3 ...

do

程序段

done

以上的例子来看,这个$var的变量内容在循环工作时:

1、第一次循环时,$var的内容为con1;

2、第二次循环时,$var的内容为con2;

3、第三次循环时,$var的内容为con3;

for...in...do...done案例1

假设我们有三种动物,分别是dog,cat,elephant三种,我想每一行都输出这样“There are dogs...”之类的字样。

脚本sh15.sh内容

#!/bin/bash

#Program:

#    Using for ...loop to print 3 animals

#History

#2015/06/20 Awake First release

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH

for animal in dog cat elephant

do

echo "There are ${animal}s..."

done

脚本sh15.sh执行结果如下

[root@RHEL6 scripts]# ./sh15.sh

There are dogs...

There are cats...

There are elephants...

[root@RHEL6 scripts]#

for...in...do...dones案例2

由于系统上面的各种账号都是写在/etc/passwd内的第一个字段,你能不能通过管道命令,cut找出单纯的账号名称后,以id和finger分别检查用户的标识符与特殊参数呢?由于不同的linux系统上面的账号都不一样,此时实际去获取/etc/passwd并使用循环处理就是一个可行的方案了.

脚本sh16.sh内容

cat > sh16.sh << "eof" //我要用cat直接输入的信息覆盖到sh16.sh中,且当键盘输入eof时,该次输入就结束

#!/bin/bash

#Program

#    Use id,finger command to check system account's information

#History

#2015/06/23 Awake First release

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH

users=$(cut -d ':' -f1 /etc/passwd) //依据-d的分割字符将一段信息切割成为数段,用-f取出第几段的意思,此例也就是取出每行的用户信息

for username in $users //username的变量内容为$users

do

id $username      //用于显示用户的ID,以及所属群组的ID

finger $username //命令可以让使用者查询一些其他使用者的资料

done

eof

脚本sh16.sh执行情况如下

列出每一个账号的账号id和finger信息。

[root@RHEL6 scripts]# ./sh16.sh

uid=0(root) gid=0(root) groups=0(root)

Login: root                              Name: root

Directory: /root                         Shell: /bin/bash

On since Tue Jun 23 09:05 (CST) on pts/1 from 10.10.10.1

No mail.

No Plan.

uid=1(bin) gid=1(bin) groups=1(bin),2(daemon),3(sys)

Login: bin                               Name: bin

Directory: /bin                          Shell: /sbin/nologin

Never logged in.

No mail.

No Plan.

uid=2(daemon) gid=2(daemon) groups=2(daemon),1(bin),4(adm),7(lp)

Login: daemon                            Name: daemon

Directory: /sbin                         Shell: /sbin/nologin

Never logged in.

No mail.

No Plan.

uid=3(adm) gid=4(adm) groups=4(adm),3(sys)

Login: adm                              Name: adm

Directory: /var/adm                     Shell: /sbin/nologin

Never logged in.

No mail.

No Plan.

......

这个操作还可以用在每个账号的删除、更改上面!

for...in...do...dones案例3

脚本sh17.sh内容

cat > sh17.sh << "eof

#!/bin/bash

#Program

#    Use ping command to check the network's PC state.

#History

#2015/06/23 Awake First release

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH

netwrok="192.168.1"

for sitenu in $(seq 1 100) //seq用于产生从某个数到另外一个数之间的所有整数(包含起始数和结尾数)

do

ping -c 1 -w 1 ${network}.${sitenu} &> /dev/null && result=0 || result=1 //-c 表示ping的个数(这里为1个),-w表示指定等待每个响应的最长时间(这里为1秒);&>表示将正确与错误数据写入同一个文件,如果这些都执行正确那么将result的值赋予为0,否则赋予为1

if [ "result" == 0 ]; then

echo "Server ${network}.${sitenu} is UP."

else

echo "Server ${network}.${sitenu} id DOWN.

脚本sh17.sh执行情况如下

[root@RHEL6 scripts]# . sh17.sh

Server 192.168.1.1 is UP.

Server 192.168.1.2 is DOWN.

Server 192.168.1.3 is DOWN.

Server 192.168.1.4 is DOWN.

......

ping -w参数

[root@RHEL6 ~]# ping -w 1 192.168.1.200

PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data.

--- 192.168.1.200 ping statistics ---

1 packets transmitted, 0 received, 100% packet loss, time 1000ms //指定1秒就超时

[root@RHEL6 ~]# ping -c 1 192.168.1.200

PING 192.168.1.200 (192.168.1.200) 56(84) bytes of data.

From 192.168.1.121 icmp_seq=1 Destination Host Unreachable

--- 192.168.1.200 ping statistics ---

1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 3004ms //默认的超时时间3004ms

判断式加上固定循环实例

让用户输入某个目录文件名,然后找出某目录内的文件名的权限。利用这个脚本方式,还可以很轻易第处理一些文件的特性。

脚本sh18.sh内容

[root@RHEL6 scripts]# more sh18.sh

#!/bin/bash

#Program

# User input dir name, I find the permission of files.

#History

#2015/06/23 Awake First release

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH

read -p "Please input a directory: " dir

if [ "$dir" == "" -o ! -d "$dir" ]; then //判断用户输入的变量内容是否为空,或者不是目录,如果为空或者不是目录那么执行下面的语句,就是判断用户输入的是否为目录

echo "The $dir is NOT exist in your system."

exit 1

fi

filelist=$(ls $dir) //列出所有在该目录下的文件名,包括目录名

for filename in $filelist //变量filename内容为$filelist,filelist的变量内容是ls $dir

do

perm="" //先赋予变量perm的内容为空,因为这个变量对于每个文件都要循环一次,因此先要将变量置为空,不置为空我想几个文件之后,接下来的文件都会有所有权限

test -r "$dir/$filename" && perm="$perm readable" //测试文件是否有只读属性,如果有就赋予perm的变量内容为“空和readable值?”

test -w "$dir/$filename" && perm="$perm writable" //我想知道的是这个perm="$perm writable"为什么没有覆盖上面的环境变量?这个的解释是这样,看下文吧

test -x "$dir/$filename" && perm="$perm executable"

echo "The file $dir/$filename's permission is $perm"

done

[root@RHEL6 scripts]#

perm="$perm xxx"的解读

[root@RHEL6 scripts]# perm=""

[root@RHEL6 scripts]# perm="$perm r"  //此时$perm的内容为空,如果echo $perm,那么他的值应该是r

[root@RHEL6 scripts]# perm="$perm w"  //此时$perm的内容已经是r,如果后面再跟一个w,那么echo $perm的值应该是r w

[root@RHEL6 scripts]# perm="$perm e"  //此时$perm的内容已经是r w,如果后面再跟一个e,那么echo $perm的值应该是r w e

[root@RHEL6 scripts]# echo $perm

r w e

[root@RHEL6 scripts]#

脚本sh18.sh执行情况如下

[root@RHEL6 scripts]# ./sh18.sh

Please input a directory: /root/scripts

The file /root/scripts/sh01.sh's permission is readable writable

The file /root/scripts/sh02.sh's permission is readable writable

The file /root/scripts/sh03.sh's permission is readable writable

The file /root/scripts/sh04.sh's permission is readable writable

The file /root/scripts/sh05.sh's permission is readable writable executable

The file /root/scripts/sh06-2.sh's permission is readable writable executable

......

除了上述的方法外,for循环还有另外一种写法

for ((初始值; 限制值; 执行步长))

do

程序段

done

这种写法适合于数值方式的运算当中,在for后面的括号内的三串内容意义为:

初始值:某个变量在循环当中的初始值,直接以类似i=1设置好;

限制值:当变量的值在这个限制值得范围内,就连续进行循环,例如i<=100;

执行步长:没做一次循环时变量的变化量。脚本sh19.sh的内容如下

[root@RHEL6 scripts]# more sh19.sh

#!/bin/bash

#Program

# Try do calculate 1+2+...+$(your_input)

#History

#2015/06/23 Awake First release

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin

export PATH

read -p "Please input a number, I will count for 1+2+...+your_input:" nu  //让用户输入数字,这一部分没有判断,用户可以输入任意字符,只是脚本执行不下去,我还没有写好如何限定用户输入的一定是数字才行。

s=0   //定义s的变量值为0

for ((i=1; i<=$nu; i=i+1))  //定义初始值i=1;限制值i<=$nu;执行步长i=i+1

do

s=$(($s+$i))    //小括号重点的$s的值是0,并不会循环,这个值是0+1一次,然后是0+2一次,一直到$nu

done

echo "The result of '1+2+3...+$nu' is == $s"

[root@RHEL6 scripts]#

脚本sh19.sh的执行情况

[root@RHEL6 scripts]# vi sh19.sh

[root@RHEL6 scripts]# ./sh19.sh

Please input a number, I will count for 1+2+...+your_input:100

The result of '1+2+3...+100' is == 5050

[root@RHEL6 scripts]# ./sh19.sh

Please input a number, I will count for 1+2+...+your_input:99

The result of '1+2+3...+99' is == 4950

[root@RHEL6 scripts]#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值