一、for循环定义:
将一段代码反复执行;----->进入条件;------> 退出条件;
二、语法格式:
for 变量名 in LIST
do
statement1
...
done
for VAR in LIST; do statement1; statement2; ...; done
三、LIST:列表
定义:包含至少一个元素的字符串集合;
LIST的生成方法:
(1) 直接给出;
(2) 数值列表:
(a) {start..end},例如:{1..10}
(b) seq [start [step]] end
(3) 返回列表的命令;
(4) globbing;
(5) 变量引用;
$*, $@
例如:添加3个用户,user1, user2, user3; 密码同用户名;# vim user.sh
#!/bin/bash
#
for username in user1 user2 user3 ; do
useradd $username
echo $username |passwd --stdin $username
done
# bash -n user.sh
# bash -x user.sh
例如:添加9个用户,user101...user109;密码同用户名;#!/bin/bash
#
useradd user10$n
for n in {1..9}; do
echo user10$n | passwd --stdin user10$n &>/dev/null
done
&>/dev/null 省略报告是否创建成功失败信息
四、for循环练习题:
练习1:于/tmp/test目录中创建10个空文件f1,.., f10;#!/bin/bash
#
for n in {1..10}; do
mkdir /tmp/test/file$n &>/dev/null
done
练习2:写一个脚本,
(1) 创建"/tmp/test-当前时间"目录;
(2) 添加10用户tuser1,.., tuser10;
(3) 在"/tmp/test-当前时间"目录中,创建10空文件f1,...,f10;
(4) 修改f1的属主为tuser1;依次类推;#!/bin/bash
#
directory=/tmp/test-`date +%H-%N-%S`
mkdir $directory
for i in {1..10};do
useradd tuser$i
touch $directory/f$i
chown tuser$i $directory/f$i
done
练习3:求100以内所有正整数之和;#!/bin/bash
#
sum=0
#
for n in {1..100}; do
sum=$[$n+$sum]
done
注意:sum=0也可表示为declare -i sum=0
let sum+=$i 也表示sum自身与&i相加
练习4:求100以内所有偶数之和;以及所有奇数之和;#!/bin/bash
#
ODD_SUM=0
#
EVEN_SUM=0
#
ODD_LIST=$(seq 1 2 100)
EVEN_LIST=$(seq 0 2 100)
#
for n in $ODD_LIST; do
ODD_SUM=$[$ODD_SUM+$n]
done
#
echo "一到一百的奇数和为:$ODD_SUM"
#
for m in $EVEN_LIST; do
EVEN_SUM=$[$EVEN_SUM+$m]
done
#
echo "一到一百的偶数和为:$EVEN_SUM"
练习5:计算当前系统上所有用户ID之和;#!/bin/bash
#
UID_SUM=0
UID_LIST=$(cut -d':' -f3 /etc/passwd)
#
for n in $UID_LIST; do
UID_SUM=$[$UID_SUM+$n]
done
echo "The all user ID sum is '$UID_SUM'"
练习6:传递参数(文本文件路径)给脚本,统计所有文件的空白行数之和;显示此次共对多少文件进行统计;#!/bin/bash
#
File_Sum=$#
echo "the sum of file is $File_Sum"
for i in $*; do
Space_Sum=$(grep '^[[:space:]]*$' $i | wc -l)
SPACE_ALL=$[$SPACE_ALL+$Space_Sum]
done
echo "the sum of space is $SPACE_ALL"
# $*可以直接生成文件列表
练习7:显示当前系统所有默认shell为bash的用户的总数;并统计此些用户ID之和;#!/bin/bash
#
BASH_SUM=0
BASH_SUM=$(grep 'bash$' /etc/passwd | wc -l)
echo "the sum of bash is $BASH_SUM"
UID_SUM=0
UID_LIST=$(grep 'bash$' /etc/passwd | cut -d':' -f3)
for n in $UID_LIST; do
UID_SUM=$[$UID_SUM+$n]
done
echo "the sum of BID is $UID_SUM"
grep 'bash$' /etc/passwd | cut -d':' -f3
练习8:写一个脚本
(1) 假设某目录下分别有K##和S##开头文件若干;(/etc/rc.d/rc3.d/为例;)
(2) 给此目录下的所有以K开头的文件,传递一个stop参数;(echo "/etc/rc.d/rc3.d/atd stop")
(3) 给此目录下的所有以S开头的文件,传递一个start参数;#!/bin/bash
for file in /etc/rc.d/rc3.d/K*; do
echo '$file stop' another way: echo -e "$file stop...........[\033[34mOK\033[0m]" 则后面会显示蓝色OK
done
for file in /etc/rc.d/rc3.d/S*; do
echo '$file start'
done
练习9:写一个脚本
(1) 使用Ping命令探测172.16.100.X主机的在线状态;#!/bin/bash
for host in {1..254}; do
ping -c1 -w1 172.16.100.$host
done
练习10:写一个脚本
(1) 给一个脚本传递一些用户名;
(2) 计算此些用户所属基本组的id之和;#!/bin/bash
declare -i GSUM=0
for username in $1; do
GSUM=$[$GSUM+`id -g $username`]
done
echo the GID_SUM is $GSUM
五、for的几种特殊情况:
(1) for省略,会自动获取脚本参数列表;
(2) C编程风格:
for ((变量赋值;循环条件;修正表达式)); do
CMD1
CMD2
done
例如:求100以内偶数之和#!/bin/bash
declare -i evensum=0
for ((i=2;i<=100;i+=2));do
let evensum+=$i
done
echo $evensum
(3) 循环嵌套:
for i in [LIST1]; do
CMD1
for j in [LIST2]; do
CMD2
...
done
done
练习11:写一个脚本
(1) ping 172.16.X.Y内的所有主机;
172.16.0-255.1-254#!/bin/bash
for i in {0..255}; do
for j in {1..254}; do
ping -c1 -w1 172.16.$i.$j
done
done
练习12:写个脚本
(1) 传递一些目录给脚本;
(2) 逐个显示每个目录下的所有一级文件的内容类型;
(3) 统计一个有多少个目录;一共显示了多少个文件;#!/bin/bash
#
declare -i dirs=0
declare -i files=0
for d in $*; do
for f in $d/*; do
file $f
let files++
done
let dirs++
done
echo "Directories: $dirs."
echo "Files: $files."
解析:let dirs++ 为计数器,就是循环多少次,计数为多少;等价于dir=[$dirs+1]
六、bash命令退出和退出状态码
命令在bash中执行结束退出时,其执行成功与否可通过退出状态码来记录;
脚本的退出状态码取决于执行的最后一条命令;自定义退出状态码:
exit #
成功:0
失败:1-255
注意:提前退出脚本,也可使用exit命令实现;
例如:以某条命令的状态作为脚本的退出状态码#!/bin/bash
#
ls /varr
retval=$?
echo "hello"
exit $retval
解析:retval为此条命令的输出状态码