shell脚本相关

shell脚本

字符串截取

${string:start:length}

${string:start} 省略长度,直接截取到字符串末尾

${string:0-start:length}从右面第几个字符开始向右计数‘

${string:0-start} 从右边第几个字符开始截取到字符末尾

${string#*chars} 从指定的字符chars截取其往后的字符

${string##*chars}匹配到最后一个char

${string%chars*}截取chars左边的字符

%{string%%chars*}匹配到最后的关键字

格式替换符

%s 字符串

%f 浮点格式

%d %i 十进制整数

%% 百分号本身

\n 换行符

\r 回车

\t tab

%-10s表示宽度10个字符,左对齐

[root@localhost ~]# printf "%-10s %-10s %-4s %s \n" 姓名 性别 年龄 体重 小明 男性 20岁 70KG 小红 女性 18岁 50KG 
姓名     性别     年龄 体重 
小明     男性     20岁 70KG 
小红     女性     18岁 50KG

算数运算

let var=算数表达式

var=$[算数表达式]

var=$((算数表达式))

var=$(expr 算数表达式)

echo '算数表达式' | bc -l 支持小数运算

echo "scale=3;20/3" | bc #计算数值保留三位小数

随机数生成器:$RANDOM 0-32767

生成50以内的随机数:echo $[$[$RANDOM %50]+1] 1-50

i+=1 == i=i+1

i++ 自增先赋值再运算

++i 先运算再赋值

i-- 自减

计算年龄之和:

[root@localhost shell]# cat age
a=10
b=20
c=30
[root@localhost shell]# awk -F "=" '{sum+=$2} END {print sum}' age  #sum+=$2:对每行的第二列进行累加如何赋值给sum
60

[] 和 [[]] 的区别

[]是测试语句,兼容性强,可以在所有的shell解释器

[[]] 尽可以再特定的几个shell解释器中运行

<>可以在[[]]中排序 而[]不支持

[]中使用-a -o表示逻辑与 或 [[]]用 && || 表示与 或

[ ]中的 == 是字符匹配 , [[ ]]中的 == 是模式匹配

[ ] 不支持正则 [[]] 可以用=~进行正则匹配

[ ]仅在部分Shell中支持用()进行分组,[[ ]]均支持

在[ ]中如果变量没有定义,那么需要用双引号引起来,在[[ ]]中不需要

大于 -gt

小于 -lt

等于 -eq

大于等于 -ge

小于等于 -le

不相等 -ne

-v VAR 变量var是否被定义

[root@ansible-salve1 shell]# [[ -v NAME ]]
[root@ansible-salve1 shell]# echo $?
1
[root@ansible-salve1 shell]# NAME=1
[root@ansible-salve1 shell]# [[ -v NAME ]]
[root@ansible-salve1 shell]# echo $?
0

-R VAR 变量VAR是否被引用

[root@ansible-salve1 shell]# NAME=10
[root@ansible-salve1 shell]# test -v NAME
[root@ansible-salve1 shell]# echo $?
0
[root@ansible-salve1 shell]# test -R NAME
[root@ansible-salve1 shell]# echo $?
1

文件测试表达式

-a/-e 文件是否存在

-d 文件存在且为目录则为真

-f 文件存在且为普通文件则为真

-r 文件存在且可读则为真

-w 文件存在且可写为真

-x 文件存在且可执行则为真

字符串测试表达式

-z "字符串" 若字符串长度为0则为真

"字符串1" == "字符串2" 字符串1=2的长度则为真

在[ ] 或 test中使用的比较符号 在(()) 或 [[ ]]中使用的比较符号(不用这个做数字比较) 说明
-eq \== 或 = 相等,equal
-ne != 不相等,not equal
-gt > 大于,greater than
-ge > = 大于等于,greater equal
-lt < 小于,less than
-le < = 小于等于,less equal

( )与 { }

( )和 { }都可以将多个命令组合再一次,批量执行,{ } 里的内容需要与两侧用空格隔开并在命令结尾加上;

( )会开启子shell,并且list中变量赋值及内部命令执行后,将不再影响后续的环境

{ } 不会开启子shell,在当前shell中运行,会影响当前shell环境

read命令

-a 将读取的数据赋值给数组,从下标0开始

-p 显示提示信息

-s 静默模式,不显示输入的字符

-t 设置超时时间

-n 读取n个字符而不是整行

if语句

if [ 条件判断式1 ] then 命令 elif [ 条件判断式2 ] then 命令 ... ... else 命令 fi

case语句

case 变量引用 in PAT1) 分支1 ;; PAT2) 分支2 ;; ... *) 默认分支 ;; esac

*: 任意长度任意字符 ?: 任意单个字符 []: 指定范围内的任意单个字符 |: 或,如a|b ,a或b

循环

for while

循环次数已知 for

循环次数未知 while

for循环

for name [in words ...]; do command; done

for 变量 in 列表

do

循环体

done #遍历

while 循环

while command; do commands;done

while condition;do 循环体 done

#condition:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“Ture”,则执行一次循环;直到条件测试状态为“false”终止循环,因此:condition一般应该有循环控制变量;而此变量的值会在循环不断地被修正

无限循环:

while true;do 循环体 done

until循环

格式:

until Commands;do commands;done

until condition;do 循环体 done

进入条件:condition为false

退出条件:condition为ture

无限循环:

until false;do 循环体 done

continue

continue[N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层

格式

while CONDITION1;do 循环体1 ... if command2;then continue fi CMDn .... done

break

break[N]:提前结束第N层后的全部循环;最内层为第1层,默认为1

for((i=0;i<10;i++));do for((j=0;j<10;j++));do [ $j -eq 5 ] && break echo $j done echo ---------------------------- done

Shell中的数组

Shell中,用小括号()来表示数组,数组元素之间用空格来分

#arrayname=(1 2 3 4 5)

输出定义数组中的全部元素 echo ${arrayname[*]} echo ${arrayname[@]}

输出定义数组中的第一个元素 echo ${arrayname[0]}

输出定义数组中的第二个元素 echo ${arrayname[1]}

输出定义数组中的元素个数 #echo ${#arrayname[*]}

array2=([1]=one [2]=two [3]=three) echo ${array2[*]} 输出定义数组的所有元素 echo ${array2[@]} 输出定义数组的所有元素 echo ${#array2[@]} 输出定义数组的元素个数

array3[1]=a array3[2]=b array3[3]=c

输出定义数组中的全部元素 echo ${array3[@]}

输出定义数组中的第一个元素 echo ${array3[1]}

函数

name () {

命令

return

}

在Shell脚本中,$*和$@是Shell脚本的特殊变量,作用都是获取传递给脚本或函数的所有参数

$@与$*的相同点:当它们没有被双引号包裹时,两者是没有区别的,都代表一个包含接收到的所有参数的数组,各个数组元素都是传入的独立参数

$@与$的不同点:当被双引号包裹时,$@仍为一个数组,而$会将所有参数整合成一个字符串

[root@localhost ~]# read -p "输入:" x y z
输入:1 2 3
[root@localhost ~]# echo $x
1
[root@localhost ~]# echo $y
2
[root@localhost ~]# echo $z
3
#自定义IFS变量的值 
[root@localhost ~]# IFS=$',' read -p "输入:" x y z
输入:4,5,6
[root@localhost ~]# echo $x
4
[root@localhost ~]# echo $y
5
[root@localhost ~]# echo $z
6

正则表达式

元字符 含义及用法
\ 转义字符,用于取消特殊符号的含义,例: \!\n\$
^ 匹配字符串开始的位置,例:^a^the^#^[a-z]
$ 匹配字符串结束的位置,例: word$^$匹配空行
. 匹配除\n之外的任意的一个字符,例: go.dg..d。如果想要匹配包含\n字符可以使用 [.\n]
* 匹配前面子表达式0次或者多次,例: goo*dgo.*d
[list] 匹配list列表中的一个字符,例: go[ola]d[abc][a-z][a-z0-9][0-9]匹配任意一位数字
[^list] 匹配任意非list列表中的一个字符,例:[^0-9][^A-Z0-9][^a-z]匹配任意一位非小写字母
\{n\} 匹配前面的子表达式n次,例: go\{2\}d[0-9]\{2\}匹配两位数字
\{n,\} 匹配前面的子表达式不少于n次,例: gol{2,\}d[0-9]\{2,\}匹配两位及两位以上数字
\{n,m\} 匹配前面的子表达式n到m次,例 : go\{2,3\}d[0-9]\{2,3\}匹配两位到三位数字
注: egrepawk使用{n}{n,}{n,m}匹配时 {} 前不用加 \
\w 匹配包括下划线的任何单词字符。
\W 匹配任何非单词字符。等价于[^A-Za-z0-9_]
\d 匹配一个数字字符。
\D 匹配一个非数字字符。等价于[^0-9]
\s 空白符。
\S 非空白符。
元字符 含义及用法
+ 匹配前面子表达式1次以上,例: go+d,将匹配至少一个o,如godgoodgoood
? 匹配前面子表达式0次或者1次,例: go?d,将匹配gdgod
() 将括号中的字符串作为一个整体,例1: g(oo)+d,将匹配oo整体1次以上,如goodgooood
| 以或的方式匹配字符串,例:g(oo|la)d,将匹配good或者 glad

\{n\} \{n,\} 的用法

#匹配good字符,其中\{2\}只会匹配前面的o两次
[root@localhost opt]# grep "go\{2\}d" testfile6 
good
#匹配go..d,其中o至少2次及以上
[root@localhost opt]# grep "go\{2,\}d" testfile6 
good
goood
gooood
gooooood
gooooooodddd
oooogooood

[] [^]的用法

#查询一个字符,其中有一段以go开头d结尾,中间的o、l、a这几种字符中的一种
[root@localhost opt]# grep “go[ola]d” testfile6     
good
gold
goad
#查询一个字符,其中有一段以go开头d结尾,中间的o、l、a这几种字符中的一个或多个
[root@localhost opt]# grep “go[ola]*d” testfile6 
god
good
goood
gooood
gooooood
gooooooodddd
oooogooood
gold
goad
#匹配除了a-g开头的字符
[root@localhost opt]# grep "^[^a-g]" testfile6  
oooogooood
ooooogd

* ^ $的用法

[root@localhost opt]# grep "goo*d" testfile6    
god
good
goood
gooood
gooooood
gooooooodddd
oooogooood
#查询以g开头d结尾,中间的o有0个或多个
[root@localhost opt]# grep "^goo*d$" testfile6  
god
good
goood
gooood
gooooood

sed编辑器

sed -e '操作' 文件l 文件2 ...
sed -n -e '操作' 文件1 文件2 ...
sed -f 脚本文件 文件1 文件2 ...
sed -i -e '操作' 文件1 文件2 ...

sed -e 'n{                #n意为:指定行
操作l
操作2
...
}' 文件1 文件2 ...

选项 含义
-e--expression= 表示用指定命令来处理输入的文本文件,只有一个操作命令时可省略,一般在执行多个操作命令使用。
-f--file= 表示用指定的脚本文件来处理输入的文本文件。
-h--help 显示帮助。
-n--quietsilent 禁止sed编辑器输出,但可以与p命令一起使用完成输出。
-i 直接修改目标文本文件。
-r, --regexp-extended 支持正则表达式
操作 含义
s 替换,替换指定字符。
d 删除,删除选定的行。
a 增加,在当前行下面增加一行指定内容。
i 插入,在选定行上面插入一行指定内容。
c 替换,将选定行替换为指定内容。
y 字符转换,转换前后的字符长度必须相同。
p 打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容,如果有非打印字符,则以ASCII码输出。其通常与-n选项一起使用。
= 打印行号。
l(小写L) 打印数据流中的文本和不可打印的AscII字符(比如结束符$、制表符\t)
[root@localhost ~]# sed -n -e 'p' testfile1			#打印内容

[root@localhost ~]# sed -n -e '=' testfile1			#打印行号

[root@localhost ~]# sed -n -e 'l' testfile1			#打印隐藏特殊符号

[root@localhost ~]# sed -n -e '=;p' testfile1		#打印行号和内容
[root@localhost ~]# sed -n -e '=' -e 'p'testfile1	#打印行号和内容
[root@localhost ~]# sed -n '1p' testfile1					#打印第1行

[root@localhost ~]# sed -n '$p' testfile1					#打印最后一行

[root@localhost ~]# sed -n '1,3p' testfile1					#打印1到3行

[root@localhost ~]# sed -n '3,$p' testfile1					#从第3行开始打印,直到最后一行结束

[root@localhost ~]# sed -n '1,+3p' testfile1				#打印第1行之后的连续3行,即1-4行

[root@localhost ~]# sed '5q' testfile1						#打印前5行信息后退出,q表示退出

[root@localhost ~]# sed -n 'p;n' testfile1					#打印奇数行,n表示移动到下一行
[root@localhost ~]# sed -n '3{p;n;n;p}' testfile1			#打印第3,5行

[root@localhost ~]# sed -n 'n;p' testfile1					#打印偶数行
root@localhost ~]# sed -n '2,${n;p}' testfile1				#从第2行开始,从下一行开始打印,即第3、5、7行

[root@localhost ~]# sed -n '/user/p' /etc/passwd			#打印包含user的行

[root@localhost ~]# sed -n '/^a/p' /etc/passwd				#打印以a开头的行

[root@localhost ~]# sed -n '/bath$/p' t/etc/passwd			#打印以bath结尾的行

[root@localhost ~]# sed -n '/ftp\|root/p' /etc/passwd		#打印含有ftp或者root的行
[root@localhost ~]# sed -nr '/ftp|root/p' /etc/passwd		#-r表示支持扩展正则表达式

[root@localhost ~]# sed -n '2,/nobody/p' /etc/passwd		#打印从第2行开始,直到第一个包含nobody的行结束

[root@localhost ~]# sed -n '2,/nobody/=' /etc/passwd		#打印从第2行开始,直到第一个包含nobody的行结束的行号

[root@localhost ~]# sed -nr '/ro{1,}t/p' /etc/passwd		#打印包含root的行,root中o的个数可以是1个以上
[root@localhost ~]# sed 'd' testfile1						#全删

[root@localhost ~]# sed '3d' testfile1						#删除第3行

[root@localhost ~]# sed '2,4d' testfile1					#删除第2到4行

[root@localhost ~]# sed '$d' testfile1						#删除最后一行

[root@localhost ~]# sed '/^$/d' testfile1					#删除空行

[root@localhost ~]# sed '/nologin$/d' /etc/passwd			#删除以nologin结尾的文件

[root@localhost ~]# sed '/nologin$/!d' /etc/passwd			#"!"表示取反

[root@localhost ~]# sed '/2\|3/d' testfile2					#删除第2行和第3行
[root@localhost ~]# sed '/2/,/3/d' testfile2				#从第一个位置打开行删除功能,到第二个位置关闭行删除功能
[root@localhost ~]# sed '/1/,/3/d' testfile2				#从第一个包含1的行打开删除功能,到第一个包含3的行关闭删除功能,然后接着往下扫描重复之前操作,若包含3的行不存在,则一删到底。
操作
g 表明新字符串将会替换所有匹配的地方
数字 表明新字符串将替换第几处匹配的地方
p 打印与替换命令匹配的行,与-n一起使用
w 文件 将替换的结果写到文件中
[root@localhost ~]# sed -n 's/root/admin/p' /etc/passwd					#将匹配行中第一个root替换为admin然后打印替换的行
	
[root@localhost ~]# sed -n 's/root/admin/2p' /etc/passwd				#将匹配行中第二个root替换为admin然后打印替换的行

[root@localhost ~]# sed -n 's/root/admin/gp' /etc/passwd				#将匹配行所有root替换为admin然后打印替换的行
[root@localhost ~]# sed -n 's/root/admin/gw file' /etc/passwd			#将匹配行所有root替换为admin然后保存替换的行至file
[root@localhost ~]# sed -n 's/root/admin/gp' /etc/passwd > file			#将匹配行所有root替换为admin然后保存替换的行至file

[root@localhost ~]# sed 's/root//g' /etc/passwd							#将匹配行所有root替换为空的

[root@localhost ~]# sed 'l,20 s/^/#/' /etc/passwd						#在第1到20行进行注释
[root@localhost ~]# sed '/^root/ s/^/#/' /etc/passwd					#将以root开头的行进行注释

[root@localhost ~]# sed '/root/ s/^/#/' /etc/passwd						#将包含root的行进行注释
[root@localhost ~]# sed -rn 's /.*root.*/#&/p' /etc/passwd				#用正则匹配行内容,然后通过&获取前面匹配的内容进行注释后打印
[root@localhost ~]# sed  -ir 's/.*swap.*/#&/' /etc/fstab				#禁用swap交换空间
[root@localhost ~]# sed -f script.sed testfile2							#对某个文件执行指定命令文件

[root@localhost ~]# sed '1,20w out.txt' /etc/passwd
[root@localhost ~]# sed '1,20 s/^/#/w out.txt' /etc/passwd				#将文件的第1到20行进行注释,然后将修改的行内容保存至指定文件

[root@localhost ~]# sed -n 's/\/bin\/bash/\/bin\/csh/p' /etc/passwd		#将文件中/bin/bash替换为/bin/csh,然后打印替换的行
[root@localhost ~]# sed -n 's!/bin\/bash!/bin\/csh!p' /etc/passwd		#使用"!"作为字符串分隔符,可以使用除了斜杠的其他字符
[root@localhost ~]# sed '/45/c ABC' testfile2							#将含有45的行都替换为ABC

[root@localhost ~]# sed 'y/145/ABC/' testfile2							#使所有的1字符转换成a,所有的2字符转换成B,所有的3字符转换成c

[root@localhost ~]# sed '1,3a ABC' testfile2							#在第1行到第3行后都插入ABC新的一行

[root@localhost ~]# sed '1i ABC' testfile2								#在第一行前插入ABC新的一行

[root@localhost ~]# sed '5r /etc/resolv.conf' testfile2					#在第5行读取/etc/resolv.conf文件

awk编辑器

awk 选项 '模式或条件 {操作}' 文件1 文件2 ...
awk -f 脚本文件 文件l 文件2 ...

awk -F ',' '{print}' file1

内建变量 含义
FS 列分割符。指定每行文本的字段分隔符,默认为空格或制表位。与-F作用相同。
NF 当前处理的行的字段个数。$NF代表最后一个字段。
NR 当前处理的行的行号(序数)。
$0 当前处理的行的整行内容。
$n 当前处理行的第n个字段(第n列)。
FILENAME 被处理的文件名。
RS 行分隔符。awk从文件上读取资料时,将根据Rs的定义把资料切割成许多条记录,而awk比较倾向于将一行分成多个一次仅读入一条记录,以进行处理。预设值是\n
[root@localhost opt]# awk '{print $0}' testfile1 
[root@localhost opt]# awk '{print}' testfile1 
输出所有内容
###输出第1行内容
[root@localhost opt]# awk 'NR==1 {print}' testfile1 
one

###输出第3行内容
[root@localhost opt]# awk 'NR==3 {print}' testfile1 
three

###输出第1~3行内容
[root@localhost opt]# awk 'NR==1,NR==3 {print}' testfile1 
one
two
three
[root@localhost opt]# awk '(NR>=1)&&(NR<=3){print}' testfile1
one
two
three

###输出第1行、第3行的内容
[root@localhost opt]# awk 'NR==1||NR==3 {print}' testfile1 
one
three

###输出偶数行的内容
[root@localhost opt]# awk '(NR%2)==0{print}' testfile1 

###输出奇数行的内容
[root@localhost opt]# awk '(NR%2)==1{print}' testfile1 
###输出含有root的行
[root@localhost opt]# awk '/root/{print}' /etc/passwd


###输出以root开头的行
[root@localhost opt]# awk '/^root/{print}' /etc/passwd

###输出以nologin结尾的行
[root@localhost opt]# awk '/nologin$/{print}' /etc/passwd
 [root@localhost opt]# awk 'BEGIN {x=0};/\/bin\/bash$/{x++};END {print x}' /etc/passwd
2
###输出第3个字段的值小于5的第1、3个字段内容
[root@localhost opt]# awk -F":" '$3<5{print $1,$3}'
###输出第3个字段不小于200的行
[root@localhost opt]# awk -F":" '!($3<200){print $1,$3}' /etc/passwd
[root@localhost opt]# awk 'BEGIN{FS=":"};{if($3>=1000){print}}' /etc/passwd

你可能感兴趣的:(服务器,linux,运维)