${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环境
-a 将读取的数据赋值给数组,从下标0开始
-p 显示提示信息
-s 静默模式,不显示输入的字符
-t 设置超时时间
-n 读取n个字符而不是整行
if [ 条件判断式1 ] then 命令 elif [ 条件判断式2 ] then 命令 ... ... else 命令 fi
case 变量引用 in PAT1) 分支1 ;; PAT2) 分支2 ;; ... *) 默认分支 ;; esac
*: 任意长度任意字符 ?: 任意单个字符 []: 指定范围内的任意单个字符 |: 或,如a|b ,a或b
for while
循环次数已知 for
循环次数未知 while
for name [in words ...]; do command; done
for 变量 in 列表
do
循环体
done #遍历
while command; do commands;done
while condition;do 循环体 done
#condition:循环控制条件;进入循环之前,先做一次判断;每一次循环之后会再次做判断;条件为“Ture”,则执行一次循环;直到条件测试状态为“false”终止循环,因此:condition一般应该有循环控制变量;而此变量的值会在循环不断地被修正
无限循环:
while true;do 循环体 done
格式:
until Commands;do commands;done
until condition;do 循环体 done
进入条件:condition为false
退出条件:condition为ture
无限循环:
until false;do 循环体 done
continue[N]:提前结束第N层的本轮循环,而直接进入下一轮判断;最内层为第1层
格式
while CONDITION1;do 循环体1 ... if command2;then continue fi CMDn .... done
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
中,用小括号()
来表示数组,数组元素之间用空格来分
#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.d 、g..d 。如果想要匹配包含\n字符可以使用 [.\n] |
* |
匹配前面子表达式0次或者多次,例: goo*d 、 go.*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\} 匹配两位到三位数字 |
注: egrep 、 awk 使用{n} 、{n,} 、{n,m} 匹配时 {} 前不用加 \ |
|
\w |
匹配包括下划线的任何单词字符。 |
\W |
匹配任何非单词字符。等价于[^A-Za-z0-9_] 。 |
\d |
匹配一个数字字符。 |
\D |
匹配一个非数字字符。等价于[^0-9] 。 |
\s |
空白符。 |
\S |
非空白符。 |
元字符 | 含义及用法 |
---|---|
+ |
匹配前面子表达式1次以上,例: go+d ,将匹配至少一个o ,如god 、good 、goood 等 |
? |
匹配前面子表达式0次或者1次,例: go?d ,将匹配gd 或god |
() |
将括号中的字符串作为一个整体,例1: g(oo)+d ,将匹配oo 整体1次以上,如good 、gooood 等 |
| |
以或的方式匹配字符串,例: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 -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 、--quiet 或silent |
禁止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 选项 '模式或条件 {操作}' 文件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