shell笔记
- 一、Linux下的shell与内核
- 1 什么是Shell?
- 2 linux启动过程
- 3 shell编程
- 二、变量与变量应用
- 1 什么是变量?
- 2 变量分类
- 3 变量赋值格式
- 4.变量命名方式
- 5.变量声明
- 6.变量引用
- 7.变量清除
- 8.变量只读
- 9 内部参数变量
- 10 常见环境变量
- 11 变量应用
- 14 字符串长度与截取
- 15 同时输出多行信息
- 16 命令替换:
- 17 read命令
- 18 整数测试符
- 19 字符串操作符
- 19 比较符
- 20 逻辑测试操作符:与、或、非
- 21 算术运算指令expr
- 22 条件测试语句
- 四、正则表达式
- 1 .匹配任意字符
- 2 * 匹配前一个字符的0个或多个实例
- 3 ^ 匹配输入字符串的开头
- 4 $ 匹配行尾
- 5 [] 匹配字符集合
- 6 \<\> 精确匹配符号
- if else
- 1 简单if结构
- 2 if/else结构
- 3 if/elif/else 结构
- 4 if/else使用注意事项
- case
- 1 case语法结构
- for循环
- 1 列表for循环
- 2 不带列表for循环
- 3 for循环举例
- 例1 所有文件名大写替换为小写
- 例2 读取/etc/passwd文件,依次输出ip段
- 例3 读取/etc/hosts内容for循环,执行ping
- 例4 循环ip列表,输出对应编号
- 例5 批量添加用户
- break
- 例1 break
- continue
- 例1 continue
一、Linux下的shell与内核
1 什么是Shell?
Shell 是一种具备特殊功能的程序,它提供了用户与内核进行交互操作的一种接口。它接收用户的命令,并把它送入内核去执行。
那什么是内核(kernel)?
内核是Linux系统的心脏,从开机自检时就驻留在计算机的内存中,直到计算机关闭为止,而用户的应用程序存储在计算机的硬盘上,仅当需要时才会被调入内存。
2 linux启动过程
BIOS->MBR->BootLoader(grub)->kernel->init->系统初始化->shell
Shell是一种应用程序,当用户登录Linux系统时,Shell就会被调入内存执行。Shell独立于内核,它是连接内核和应用程序的桥梁,并由输入设备读取命令,再将其转为计算机可以理解的机械码,Linux内核才能执行该命令。
shell在Linux系统的位置:
shell也是一个命令显示器,我们敲的命令传递给内核,内核返回一个结果,内核给我们看到的结果,就是叫shell。
Shell也是一个命令行解释器,它为用户提供了一个向Linux内核发送请求以便运行程序的界面系统级程序,用户可以用Shell来启动、挂起、停止甚至是编写一些程序。
3 shell编程
Shell还是一个功能相当强大的编程语言, 易编写,易调试,灵活性较强。
Shell是解释执行的脚本语言,在Shell中可以直接调 用Linux系统命令。
Shell打开方式两种:Linux终端、远程工具
linux支持的shell,cat /etc/shells会显示。
cat /etc/shells
shell脚本的格式是怎样的呢?shell的一条命令只做一件事,为了组合命令和多次执行,使用脚本文件来保存需要执行的命令。
命令组合
cd /var/ ; ls ; pwd ; du -sh *
如果是编写成shell,vim 1.sh
cd /var/ ; ls ; pwd ; du -sh *
shell脚本的执行方式?
bash 1.sh #不需要赋权,不会产生子进程
./ 1.sh #需要可执行权限,不会产生子进程(即脚本进入目录后,脚本结束会回到原目录)
chmod u+rx filename #赋予该脚本执行权限
内建命令和外部命令区别?
内建命令不会产生子进程,内建命令对当前shell生效
二、变量与变量应用
1 什么是变量?
变量用于保存有用信息,如路径名、文件名、数字等。Linux用户使用变量定制其工作环境,使系统获知用户相关配置。本质上是存储数据的一个或多个计算机内存地址。
2 变量分类
用户自定义变量,由用户自己定义、修改、使用
环境变量path,这类变量由系统维护
位置参数变量,这类变量通过命令行给程序传递执行参数
内部参数变量,是bash预定义的特殊变量,用户不能修改
3 变量赋值格式
vars=value
vars1='value key'
切记等号两边无空格,如果value中含空格,需要用引号括起来(没有空格括起来与不阔无区别)。
4.变量命名方式
– 变量名只能由字母/数字/下划线组成,区分大小写
– 变量名不能以数字开头,不要使用关键字和特殊字符
5.变量声明
使用变量前,首先要进行变量声明
shell变量为弱类型,不需要定义变量类型
变量声明与赋值格式:变量=值(等号两边不能有空格)
6.变量引用
$变量名 #1个字符建议用,如$a
${变量名} #多于1个字符建议使用这种方式,如${abc}
echo $变量 #显示变量用echo
7.变量清除
变量不需使用时,用unast进行清除,
格式:unast 变量名
8.变量只读
变量设置为只读用readonly,任何用户不能对此变量进行重新赋值
格式: vars=value
readonly vars
9 内部参数变量
Shell内部参数变量是一组特殊的变量,它们由Shell自动设置和维护,用于存储有关Shell和正在运行的命令的信息。以下是一些常见的Shell内部参数变量及其用途:
内部参数变量与含义:
1.$0:保存当前脚本或命令的名称。
2.$1, $2, $3, …:这些变量保存传递给脚本或函数的位置参数,例如,$1保存第一个参数,
2
保存第二个参数,以此类推。
3.
2保存第二个参数,以此类推。 3.
2保存第二个参数,以此类推。3.#:保存传递给脚本或函数的位置参数的数量。
4.
@
:保存所有传递给脚本或函数的位置参数的列表。
5.
@:保存所有传递给脚本或函数的位置参数的列表。 5.
@:保存所有传递给脚本或函数的位置参数的列表。5.*:保存所有传递给脚本或函数的位置参数的列表,作为一个单独的字符串。
与进程相关的内部参数与含义:
6.$
:保存当前
S
h
e
l
l
进程的进程
I
D
(
P
I
D
)。
7.
:保存当前Shell进程的进程ID(PID)。 7.
:保存当前Shell进程的进程ID(PID)。7.?:保存上一个命令的退出状态(返回值)。通常,0表示成功,非零值表示出现了错误。
8.
!
:保存在后台运行的最后一个命令的
P
I
D
。
9.
!:保存在后台运行的最后一个命令的PID。 9.
!:保存在后台运行的最后一个命令的PID。9._表示在此之前执行的命令或脚本的最后一个参数
10 常见环境变量
PWD
PATH
USER
LOGNAME
SHELL
HOME
11 变量应用
退出返回状态
$? 返回0 表示成功
$? 返回1 表示通用错误或执行失败
$? 返回126 命令或脚本没权限
$? 返回127 命令没找到
[root@localhost]# echo $$ #显示当前进程的pid
2163
[root@localhost]# echo $? #显示上一条命令的返回值
0
[root@localhost ]# bash #调用子shell
[root@localhost ]# echo $$
4539
[root@localhost ]# exit 1 #指定返回值并返回父shell
exit
[root@localhost ]# echo $?
1
[root@localhost ]# display #执行不存在的命令
-bash: display: 未找到命令
[root@localhost ]# echo $? #查看返回值
127
[root@localhost ]# touch test.sh
[root@localhost ]# ./test.sh #执行不具权限的命令
-bash: ./test.sh: 权限不够
[root@localhost ]# echo $? #查看返回值
126
14 字符串长度与截取
使用${#string}来获取字符串的长度,其中string是你要测量长度的字符串。
使用${string:position:length}来截取字符串,其中string是原始字符串,position是截取的起始位置(从0开始计数),length是截取的字符数。
删除开头
echo ${josh#t}
删除结尾
echo ${josh%e}
15 同时输出多行信息
echo命令输出多行信息,多行中间不能出现双引号,否则会提前结束,或者使用转义\
[root@localhost tmp]# echo "
line1
line2
line3
"
line1
line2
line3
cat输出多行,多行中不能出现END开始的行,否则提前结束
[root@localhost tmp]# cat <<END
line1
line2
line3
END
line1
line2
line3
16 命令替换:
统计ssh的进程数
sshnum=`ps -ef | grep sshd|wc -l`
sshnum1=$(ps -ef | grep sshd|wc -l)
17 read命令
read命令用于接收键盘输入内容位变量赋值:
read [-p "信息"] [var1 var2 ...]
双引号:允许通过$符号引用其他变量值
单引号:禁止引用其他变量值,则$视为普通字符
反撇号:将命令执行结果输出给变量
#!/bin/bash
echo "========read======="
echo -e "what is your name? \c"
read name
echo "Hello $name"
echo "===================="
echo -n "where do you work?"
read
echo "I guess $REPLY keeps you busy!"
echo
read -p "Enter your job title:"
echo "I thought you might be a $REPLY."
echo
echo "=== End of the script ==="
read [-p "信息"] [var1 var2 ...]
read 操作一个变量
read操作多个变量
18 整数测试符
[ intl -eq int2 ] intl等于int2
[ intl -ne int2] intl 不等于int2
[ intl -gt int2 ] intl 大于int2
[ intl -ge int2] int1大于或等于int2
[ intl -It int2 ] intl小于int2
[intl -le int2] int1小于或等于int2
[[ intI -eq int2 ]] intl等于int2返回真
[[ int1 -ne int2 ]] intl不等于int2返回真
[[ intl -gt int2 ]] int]大于int2返回真
[[ intl -ge int2 ]] int1大于或等于int2返回真
[[ intl -It int2 ]] int]小于int2返回真
[[ intl -le int2 ]] int1小于或等于int2返回真
19 字符串操作符
字符串操作符 含义
[ -z str ] 如果字符串str长度为0,返回真
[-n str ] 如果字符串 str 长度不为 0,返回真
[ str ] 如果字符串str 不为空,返回真
[ strl = str2 ] 测试字符串str]是否与字符串str2相等,可使用--代替-
[ str1 != str2 ] 测试字符串str1是否与字符串str2不相等,但不能用!-代替!
[[ strl -- str2 ]] 两字符串相同返回真
[[ strl != str2 ]] 两字符串不相同返回真
[[ strl -~ str2 ]] str2是strl的子串返回真
[[ strl > str2 ]] str1大于str2返回真
[[ strl < str2 ]] str1小于st2返回真
19 比较符
-eq //equals等于
-ne //no equals不等于
-gt //greater than 大于
-lt //less than小于
-ge //greater equals大于等于
-le //less equals小于等于
20 逻辑测试操作符:与、或、非
匹配模式的逻辑测试操作符,需要写在双中括号中
[[ p1 && p2 ]] 逻辑与,都为真时,结果为真
[[ p1 || p2 ]] 逻辑或,有一个为真时,结果为真
[[ p1 ! p2 ]] 逻辑非
[root@localhost shell]# x=1;name=Tom;
[root@localhost shell]# [[ $x -eq 1 && $name = To? ]] ; echo $?
0
注意在逻辑测试中,-a、-0 的含义,一个是逻辑与,一个是逻辑或。
算术运算扩展不能对浮点数进行运算
# 加法
result=$((2 + 3))
echo $result # 输出:5
# 减法
result=$((5 - 2))
echo $result # 输出:3
# 乘法
result=$((2 * 3))
echo $result # 输出:6
# 除法
result=$((10 / 2))
echo $result # 输出:5
# 取余数
result=$((10 % 3))
echo $result # 输出:1
21 算术运算指令expr
expr是一个Linux命令行工具,用于进行算术运算、字符串比较、匹配、提取、长度计算,还可以用于判断变量或参数是否位整数,是否为空、为0。
1. 计算字符串长度:
expr length "hello world"
输出:11
2. 提取字符串:
expr substr "hello world" 2 5
输出:ellow
3. 查找字符串中第一个字符出现的位置:
expr index "hello world" e
输出:2
4. 进行减法运算:
expr 5 - 2
输出:3
5. 进行乘法运算:
expr 2 \* 3
输出:6
6. 进行除法运算:
bash
expr 10 / 3
输出:3
7. 进行取余数运算:
expr 10 % 3
输出:1
8. 进行逻辑与运算:
expr 2 -gt 1 && echo "True" || echo "False"
输出:True
9. 进行逻辑或运算:
expr 1 -le 0 || echo "True" || echo "False"
输出:False
10. 进行逻辑非运算:
expr 0 -eq 0 || echo "True" || echo "False"
输出:False
22 条件测试语句
test 命令在 shell 中主要用于条件测试,如果条件为真,则返回一个0值。如果表达式不为真,则返回一个大于 0的值,也可以将其称为假值。
test 命令支持测试的范围包括:字符串比较、算术比较、文件是否存在、文件属性和类型判断等。例如,判断文件是否为空、文件是否存在、是否是目录、变量是否大于3、字符串是否等于ivey、字符串是否为空等。
[root@localhost tmp]# x=8;y=12
[root@localhost tmp]# test $x -gt $y #gt表示大于
[root@localhost tmp]# echo $?
1
[root@localhost tmp]# test $x -lt $y #lt表示小于
[root@localhost tmp]# echo $?
0
方括号测试表达式
方括号代替test,方括号前后都留空格
[root@localhost tmp]# x=8;y=12
[root@localhost tmp]# [ $x -gt $y ];echo $?
1
[root@localhost tmp]# [ $x -lt $y ];echo $?
0
四、正则表达式
正则表达式是由一系列特殊字符组成的字符串,每个特殊字符都被称为元字符,元字符并不表示字面上的含义,而都有特定的含义。
正则表达式由普通字符和元字符组成的集合,这个集合用来匹配模式。正则表达式的功能就是文本查询和字符串操作,它可以匹配文本的一个字符与字符集合。
例如a、b、1、2等字符属于普通字符,普通字符可以按照字面理解,
而*、^、[]等元字符,shell赋予了他们超越字面意思的意义,如*字面意思是符号,实际却表示重复前面的字符0次或多次的隐藏含义。
正则表达式组成:
一个正则表达式由下列1项或多项组成:
1.一个字符集: 普通字符
2.锚: 指定了正则表达式要匹配的文本在文本行中所处的位置,如^和$就锚
3.修饰符 扩大或缩小正则表达式匹配文本的范围,修饰符含星号、括号和反斜杠
常见的正则表达式
正则表达式由一系列特殊字符组成,其中每个字符都有特定的含义和功能。以下是一些常见的正则表达式字符和功能:
. 匹配任意字符(除了换行符)
* 匹配前一个字符的0个或多个实例
+ 匹配前一个字符的1个或多个实例
? 匹配前一个字符的0个或1个实例
^ 匹配输入字符串的开头
$ 匹配输入字符串的结尾
\ 转义符
[] 匹配字符集合
\<\> 精确匹配符号
\{n\} 匹配前面字符出现n次
\{n,\} 匹配前面字符至少出现n次
\{n,m\} 匹配前面字符出现n次与m次之间
[abc] 匹配方括号内的任意一个字符(这里是a、b或c)
[^abc] 匹配除方括号内字符之外的任意字符
\\d 匹配任意数字字符
\\D 匹配任意非数字字符
\\s 匹配任意空白字符(包括空格、制表符等)
\\S 匹配任意非空白字符
\\w 匹配任意字母、数字或下划线字符
\\W 匹配任意非字母、数字或下划线字符
1 .匹配任意字符
.用于匹配任意字符,…73表示前面3个字符为任意字符,第4和第5 个字符为7和3
2 * 匹配前一个字符的0个或多个实例
*用于匹配前面一个普通字符的0次或多次
cat hell0.txt | grep l*
3 ^ 匹配输入字符串的开头
^2表示匹配以2开头的行
4 $ 匹配行尾
$匹配行尾
cat josh.txt | grep josh$
^$ 匹配空白行
cat josh.txt | grep ^$ #匹配空行
cat josh.txt | grep josh$ #匹配以josh结尾的字符的所有行
5 [] 匹配字符集合
[]匹配字符集合,将匹配中括号字符集中的某一字符
匹配字符j
cat josh.txt | grep [j] #匹配带j的行
匹配26字母顺序[a-b]间任意字符,
匹配任意小写字母或数字
匹配范围除a~z之外的任意一个字符
6 <> 精确匹配符号
if else
if判断是shell编程中使用频率最高的语法结构
1 简单if结构
最简单的if执行结构如下所示:
if expression #expression 表示测试条件
then
command #满足expression后要执行的命令
command
...
f1
使用这种简单 if 结构时,要特别注意测试条件后如果没有:,则 then 语句要换行,否则会产生不必要的错误。如果 f和 then 处于同一行,则必须用;。
脚本1
#!/bin/bash
##filename:youok.sh
echo "Are you ok?"
read answer
if [[ $answer == [Yy]* || $answer == [Mm]aybe ]] #没有";",then需要换行
then
echo "Glad to hear it."
fi
if 的条件判断部分使用了扩展的 test 语[[·]],[[]]中可以使用正则表达式进行条件匹配,脚本功能是读取输入内容
这个脚本提供了一个基本的用户互动,并根据他们的输入做出不同的回应。如果用户输入以 ‘Y’ 或 ‘y’ 开头,或者是 “maybe”,它将做出积极的回应。
[root@localhost tmp]# sh youok.sh
Are you ok?
Y
Glad to hear it.
[root@localhost tmp]# sh youok.sh
Are you ok?
maybe
Glad to hear it.
脚本2
#!/bin/bash
echo "你好!你今天心情如何?(请输入 '好' 或 '不好')"
read mood
if [[ $mood == [好好]* ]]; then
echo "很高兴听到你心情不错!"
elif [[ $mood == [不不好]* ]]; then
echo "抱歉听到你心情不好,有什么我可以帮助你的吗?"
else
echo "我不太明白你的回答。"
fi
脚本会询问用户今天的心情如何,然后根据用户的回答做出不同的回应
[root@localhost tmp]# sh youok_1.sh
你好!你今天心情如何?(请输入 '好' 或 '不好')
好
很高兴听到你心情不错!
[root@localhost tmp]# sh youok_1.sh
你好!你今天心情如何?(请输入 '好' 或 '不好')
不好
抱歉听到你心情不好,有什么我可以帮助你的吗?
[root@localhost tmp]# sh youok_1.sh
你好!你今天心情如何?(请输入 '好' 或 '不好')
?
我不太明白你的回答。
2 if/else结构
if/else 结构也是经常使用的,这个结构是双向选择语句,当用户执行脚本时如果不满足if后的表达式,就会执行 else 后的命令,所以有很好的交五性。其结构为:
if expression1 #expression1表示测试条件
then
command #满足#expression1条件,则执行下面这些命令
...
command
else
command ##不满足#expression1条件,则执行下面这些命令
...
command
fi
#!/bin/bash
if [$# -eq 1] #满足$# -eq 1会执行if-else嵌套语句,$#代表输入参数个数
then
if who | grep ^$1>/dev/null #判断
then echo "$1 is active."
else echo "$1 is not active."
fi
else
echo "Usage:$0<username>"
exit
fi
3 if/elif/else 结构
if/elif/else 结构用于更复杂的判断,它针对多个条件执行不同操作,语法结构如下:
if expr1 ##如果expr1条件成立(返回值为0)
then #那么
commands1 #执行语句块commands1
elif expr2 ##若expr1条件不成立,而expr2条件成立
then #那么
commands2 #执行语句块commands2
...... #可以有多个elif语句,依次执行
else #else 最多只能有一个
commands4 #执行语句块commands4
fi #if语句必须以单词 fi终止
#!/bin/bash
##filename:askage.sh
read -p "How old are you?" age #通过read读取键盘输入,输入值赋值给age
#使用shell算术运算符(())进行条件测试
if ((age < 0 || age > 120));then #判断age范围,小于0或大于120,给超出范围提示
echo "OUT of range!"
exit 1
fi
#使用多分支语句
if ((age>=0&&age<13));then
echo "child"
elif ((age>=13&&age<20));then
echo "callan"
elif ((age>=20&&age<30));then
echo "PIII"
elif ((age>=30&&age<40));then
echo "PIV"
else
echo "sorry i asked"
fi
4 if/else使用注意事项
1.if语句必须以if开头,以fi结束。
2.elif可以有任意多个(0个或多个)。
3.else 最多只能有一个(0个或1个)。
4.commands为可执行语句块,如果为空,需使用shell提供的空命令:,即冒号。该命令不做任何事情,只返回一个退出状态0。
5.expr 通常为条件测试表达式;也可以是多个命令,以最后一个命令的退出状态为条件值。
6.if语句可以嵌套使用。
case
1 case语法结构
Caseesac语句与其他语言中的switch·.case 语句类似,是一种多分支选择结构。case语句匹配一个值或一个模式,如果匹配成功,执行相匹配的命令。
case语法结构:
case expr in #expr为表达式,关键词in不要忘
pattern1) #若expr与pattern1匹配,注意括号
commands1 #则执行语句块commands1
;; #跳出case结构
pattern2) #expr与pattern2匹配
commands2 #则执行语句块commands2
;; #跳出case结构
...... #可以有任意多个模式匹配
*) #若expr与上面的模式都不匹配
commands #执行语句块commands
;; #跳出case结构
esac #跳出case结构
case 选择语句的几点说明:
在使用case选择语句的时候,需要注意如下几点:
1.表达式expr 按顺序匹配每个模式,一旦有一个模式匹配成功,则执行该模式后面的所有命令,然后退出case。
2.如果 expr 没有找到匹配的模式,则执行默认值*)后面的命令块(类似于 if 中的else)。*)可以不出现。
3.匹配模式pattern 中可以含有通配符和。
4.每个命令块的最后必须有一个双分号,可以独占一行,或放在最后一个命令的后面。
#!/bin/bash
##filename:case1.sh
echo "what is your preferred scripting language?"
read -p "1)bash 2)perl 3)python 4)ruby:" lang
case $lang in
1) echo "you selected bash" ;;
2) echo "you selected perl" ;;
3) echo "you selected python" ;;
4) echo "you selected ruby" ;;
esac
#!/bin/bash
##filename:case_fruit.sh
echo "which is your preferred fruit?"
read -p "Apple,Pear,Kiwi,Lemon,Orange,Banana:" pi #读取输入内容,赋值给变量pi
case $pi in #如果输入内容pi
[Aa]*|[Pp]*) echo "You selected Apple/Pear." ;; #是Aa/Pp输出"You selected Apple/Pear."
[Kk]*|[Ll]*) echo "You selected Kiwi/Lemon." ;;
[Oo]*|[Bb]*) echo "You selected Orange/Banana" ;;
*) echo "No fruit i like." ;; #输入内容非以上选项,则表示没有喜欢的水果
esac
for循环
1 列表for循环
- 列表for循环的语法结构如下:
for variablein list #每一次循环,依次把列表list 中的一个值赋给循环变量
do #循环体开始的标志
commands #循环变量每取一次值,循环体就执行一遍commands
done #循环结束的标志,返回循环顶部
列表 list 可以是命令替换、变量名替换、字符串和文件名列表(可包含通配符),每列表项以空格间隔。
for 循环执行的次数取决于列表 list 中单词的个数,可以省略in list,省略时相当于in"$@"。
- 例1:
#!/bin/bash
##filename:for1.sh
for x in centos ubuntu windows max
do
echo "$x"
done
将字符串列表作为list,list包含centos ubuntu windows max,字符串以空格分割,for循环会把list列表依次输出
- 例子2,列表中包含"centos ubuntu" "windows 7 10"带空格的列表项,必须要用双引号括起来作为一个整体。
#!/bin/bash
##filename:for2.sh
for x in linux "centos ubuntu" windows "windows 7 10"
do
echo "$x" ;
done
4. 例3,”== ls ==“是echo "$x"的输出结果,而40k这种信息是eval $x的输出结果(eval会将 $x 替换为没命令),然后执行命令,输出结果
#!/bin/bash
#filename:for3.sh
for x in ls "df -h" "du -sh"
do
echo "==$x==" ; eval $x
done
5. 列表for循环执行流程:
首先将list的item1 赋给 variable,然后执行 do和done 之间的命令接着再将 list的item2赋给 variable,继续执行 do和done 之间的命令,如此循环,直到 list中的所有item值都已经用完才退出循环
2 不带列表for循环
- 不带列表的for循环执行是由用户指定参数和参数的个数,不带列表的for循环的基本格式:
不带列表的for循环的基本格式:
for variable
do
command
command
..
done
其中 do和done之间的命令称为循环体,shell 会自动地将命令行输入的所有参数依次组织成列表,每次将一个命令行输入的参数显示给用户,直至所有的命令行中的参数都显示给用户。
- 例子1,所有输入的内容,都是通过脚本参数传递进去的,所以说,不带列表的 for循环其实是使用位置参数变量 "$ @"来传递 for 中的 list列表,其实相当于for 循环省略了in$@关键字。
#!/bin/bash
#filename:for4.sh
i=1
for day ; do
echo -n "positional parameter $((i++)): $day "
case $day in
[Mm]on|[Tt]ue|[Ww]ed|[Tt]hu|[Ff]ri)
echo " (weekday)"
;;
[Ss]at[Ss]un)
echo " (WEEKEND)"
;;
*) echo "(Invalid weekday)"
;;
esac
done
[root@localhost tmp]# sh for4.sh Mon Tue wed Thu Fri sat Sun ok
positional parameter 1: Mon (weekday)
positional parameter 2: Tue (weekday)
positional parameter 3: wed (weekday)
positional parameter 4: Thu (weekday)
positional parameter 5: Fri (weekday)
positional parameter 6: sat (Invalid weekday)
positional parameter 7: Sun (Invalid weekday)
positional parameter 8: ok (Invalid weekday)
3 for循环举例
例1 所有文件名大写替换为小写
#!/bin/bash
##filename:for5.sh
for fname in * ;do
fn=$(echo $fname | tr A-Z a-z)
if [[ $fname != $fn ]] ; then mv $fname $fn ; fi
done
这个脚本的功能是将当前目录下的所有的大写文件名改为小写文件名。注意,脚本中的*表示当前目录下的文件和目录。首先使用命令替换生成小写的文件名,赋予新的变量f,如果新生成的小写文件名与原文件名不同,则改为小写的文件名。
例2 读取/etc/passwd文件,依次输出ip段
#!/bin/bash
##filename:for6.sh
i=1
for username in `awk -F: '{print $1}' /etc/passwd`
do
echo "Username $((i++)) : $username"
done
for suffix in $(seq 10)
do
echo "192.168.0.${suffix}"
done
脚本实现两个功能:
第1个功能是读取/etc/passwd 文件,通过awk 获取第1列的内容作为 list,注意in 后面命令的写法,是个反引号,也就是键盘(Esc)下面的那个键,
第2个功能是通过seq 指定数字list,从1~10,然后依次输出一个IP 范围段
例3 读取/etc/hosts内容for循环,执行ping
#!/bin/bash
#filename:for7_host.sh
for host in $(cat /etc/hosts)
do
if ping -c1 -w2 $host &>/dev/null
then
echo "host ($host) is active."
else
echo "host ($host) is down."
fi
done
这个脚本的功能是通过读取/etc/hosts 的内容作为 for循环的list,然后对读取到的内容进行ping 操作,如果能够ping通,显示active,否则显示DOWN。
例4 循环ip列表,输出对应编号
#!/bin/bash
#filename:for8.sh
mynet="192.168.0"
for num in {1..6}
do
echo "IP Address $num: $mynet.$num"
done
for num in {1..10..2}
do
echo "Number: $num"
done
这个脚本是通过数值范围作为 for 循环的 lit 列表,1.6表示从1~6,而110…2是使用包含步长(increment)的数值范围作为for 循环的list,表示从1~10,每隔2个步长,执行脚本,输出如下:
例5 批量添加用户
#!/bin/bash
#filename:for9.sh
for x in {1..10}
do
useradd user${x}
echo "centos"|passwd --stdin user${x}
chage -d 0 user${x}
done
这个脚本功能是批量添加10个Linux系统用户。需要注意的是,stdin 是接受echo后面的字符串作为密码,stdin 表示非交互,直接传入密码,passwd 默认是要用终端作为标准输入,加上–stdin 表示可以用任意文件做标准输入,于是这里用管道作为标准输入。最后的chage命令是强制新建用户第1次登录时修改密码。
break
break用于强行退出当前循环,格式如下:
break [n]
如果是嵌套循环,则 break 命令后面可以跟一数字 n,表示退出第n重循环(最里面的为第1重循环)。
例1 break
#!/bin/bash
#filename:for10.sh
i=1
for day in Mon Tue Wed Thu Fri
do
echo "Weekday $((i++)) : $day"
if [ $i -eq 3 ]; then #脚本是当变量i等于3的时候退出循环,初始值为1。
break
fi
done
continue
continue 用于忽略本次循环的剩余部分,回到循环的顶部,继续下一次循环,使用方法如下:
continue [n]
如果是嵌套循环,continue命令后面也可跟一数n,表示回到第n重循环的顶部。
例1 continue
#!/bin/bash
##filename:for11.sh
i=1
for day in Mon Tue Wed Thu Fri Sat Sun
do
echo -n "Day $((i++)) : $day"
if [ $i -eq 7 -o $i -eq 8 ]; then
echo "(WEEKEND)"
continue
fi
echo "(weekday)"
done
这个脚本的含义是变量i等于1~6时,输出对应的day变量的值,并显示(weekday),当变量i等于7或者8时,输出(WEEKEND)。注意这里的S((i++)),默认i等于1,当第1个i变量传递到f语句中时,i已经是2了。执行上面脚本,输出如下: