- 需求:匹配数字的脚本,输入数字才退出
语法:[[ ^[0-9]+$ ]]
while :
do
if [[ ! $num =~ ^[0-9]+$ ]] //以数字开头
then
read -p “输入数字才退出: ” num
else
echo “thank you”
exit 1
fi
done
- 关于正则表达式的元字符
^:行首定位符
例:^A 以字母A开头
$:行尾定位符
例:love$ 以love结尾
. :匹配任意单个字符
例:a.c 可以表示任意的abc adc afc agc………
*:匹配前导符0-n次
例:grep “abc*” 1.txt 输出为ab abc abccd abcds abcccccdjjk……
(必须包含ab)
.*:任意多个字符(任何字符均可)
例:grep “.*” 2.txt
[ ]:匹配指定范围内的一个字符
例:grep [lL]ove 1.txt 输出为 love或者Love
[-]:匹配指定范围内的一个字符,连续范围
例: [a-z 0-9]ove 输出为love或者2ove
[^]:匹配不在指定范围内的字符
例:[^a-z 0-9]ove 输出为除了love和2ove的所有内容
\:用来转义元字符
例:grep “1.” 1.txt
输出为love l.ve
grep “1\.” 1.txt
输出为l.ve
\<:词首定位符
\>:词尾定位符
例:grep “love” 1.txt
输出为:love
i love you
ilove you
grep “\<love” 1.txt
输出为: love
i love you
grep “love\>” 1.txt
输出为: love
i love you
ilove you
(): \(……\)匹配稍后使用的字符的标签
例 :查找替换 :% s/172.168.202.2/172.168.202.5/
:% s/\(172.168.202.\)2/\15/
:% s/\(172.\)\(168.\)\(202.\)2/\1\2\3 5/
x\{m\} :字符出现m次
x\{m,n\}:符x出现m次到n次(包含以上也会出现)
+:匹配1-n个前导字符
例:cat 1.txt
lve
love
loove
egrep “lo+ve” 1.txt
输出为:love
loove
?:匹配0-1个前导字符
egrep “lo?ve” 1.txt
输出为:lve
love
a|b:匹配a或b
():组字符
#cat 2.txt
rs loveable lovers
#egrep “love(able|rs)” 1.txt
loveable lovers
grep----第一剑客(grep -e=egrep)
\w :所有字母与数字,称为字符[a-zA-z0-9]
\W:所有字母与数字之外的字符,称非字符,[^a-zA-z0-9]
\b:词边界 ‘\<love\>’=’\blove\b’
1.-v取反
Ps aux | grep sshd 会出现三行,有一行是grep行
Ps aux | grep sshd |grep -v grep 只有两行,grep行会消失
2.-q 静默
# grep -q “5\..” 1.txt
会输出5.1
5.2
5.aaa
5.666666
# grep -q “5\..” 1.txt 没有输出
# echo $? 输出为0
3.-R 可以查目录下的文件
#grep zhang111 /home
输出为/home 是一个目录
#grep -R zhang /home
输出会查到内容
4.-o只查这个关键字
#grep “a” 1.txt
输出为5.a
5.aa
a
aaa
ab
lovea
#grep -o “a” 1.txt
输出为a
a
a
a
a
a
5.grep -B2
查找内容加内容前两行
6.grep -A2
查找内容的后两行
7.grep -C2
查找内容的上下两行
8.egrep -l 只要文件名(过滤出包含root的目录)
9.egrep -n 带行号
#egrep -n ‘zhang111’ /etc/passwd
Sed-----第二剑客
Sed 原则: 逐行操作,内容未变,编辑文件
格式:sed 选项 命令 文件
选项: 1.-ri 在表中操作
2.-r 输出到屏幕,不会操作表中的内容
命令:
- 删除d
Sed -r ‘/^root/d’ passwd 删除以root开头的行
Sed -r ‘/root/d’ passwd 删除包含root的行
Sed -r ‘3,5d’ passwd 删除3到5行
Sed -r ‘3d;5d’ passwd 删除3行和5行
Sed -r ‘3,$d’ passwd 删除3行到最后一行
Sed -r ‘$d’ passwd 删除最后一行
- 替换命令s ( 没有全局变量一行仅换第一个)
sed -r ‘s/^root/aofo/g’ passwd 替换包含以root的行
sed -r ‘s/root/aofa/’ passwd 替换包含root行
sed -r ‘s/[0-9][0-9]$/&.5/’ passwd 查找双数结尾的词语
(将前面的双数替换成前面的双数.5)
Sed -r ‘s#(mail)#E\1#g’ passwd 将mail换一个Email
Sed -r ‘s#mail#E&#g’ passwd 将mail换成Email
&:匹配前面查找的内容
- 读文件r
#Sed -r ‘$r 1.txt’ passwd
在最后插入1.txt
#sed -r ‘/root/r 1.txt’ passwd
正则搜寻root,在root后面读取新文件
Vim中也可以读
#vim 1.txt
:$ r a.txt (在当前文件读取其他文件)
- 写文价命令 w(另存为)
#sed -r ‘w 111.txt’ 1.txt
把1.txt全部内容写入111.txt
#sed -r ‘/root/w 123.txt’ passwd
把passwd的包含root行另存到123.txt
#sed -r ‘1,5 w 123.txt ’ passwd
把1到5行另存为123.txt中
- 追加命令:a(在后面追加)
#Sed -r ‘a123’ passwd
在每行后面都追加123
#sed -r ‘2a123’ passwd
第2行后面插入123
#sed -r ‘2a 1111\
>3333\
>4444’ passwd
在第2行后面插入3行
- 插入命令i 之前(原第二行被挤到第三行)
#sed -r ‘2iaaaaa’ passwd
把第二行插入aaaaa
- 替换整行命令c
(一次替换一行)
#sed -r ‘2caaa’ passwd 替换第二行为aaaaa
(一次替换多行)
#sed -r ‘2c33333\
>555555’ passwd
8.获取下一行命令n (n下一行的意思)
#sed -r ‘/root/{n;d}’ passwd
找出root行,然后将下一行删除
#sed -r ‘/root/{n;s/bin/888/g}’ passwd
找出root行,然后将下一行的bin换成888
- 反向选择 !
#sed -r ‘2,$ d’ passwd
只剩下第一行
# sed -r ‘2,$ !d’ passwd
只删除第一行,保留2-最后行
- 多重编辑e
#sed -r -e ‘1,3d’ -e ‘4s/adm/adminuser/g’ passwd
删除1到3行,将第四行adm替换为adminuser
#sed -r ‘2s/bin/ding/g;2s/nologin/bash’ passwd
#sed -r ‘2{s/bin/ding/g;s/nologin/bash}’
将第二行bin替换为ding ,nologin替换成bash
- 删除配置文件中#注释行
#sed -r ‘/^#/d’ 1.txt
2.删除以0个或多个空或者tab,以及#号开始的行
#sed -r ‘/^[ \t]*#/d’ 1.txt
3.删除配置文件中//注释行(由于分隔符也是/所以自定义分割符\Y)
#sed -r ‘\Y^[ \t]*//Yd’ 1.txt
- 删除无内容的空行($即代表空行)
#sed -r ‘/^[ \t]*$/d’ 1.txt
- 删除注释行以及空行的另类写法
删除#行和空行
#Sed -r ‘/^[ \t]*#/d;/^[ \t]*$/d’ 1.txt
#sed -r ‘/^[ \t]*#| [ \t]*$/d’ 1.txt
用($|#)进行双选
#sed -r ‘/^[ \t]* ($|#)/d’ 1.txt
- 修改文件
#Sed -ri ‘$a\chroot_local_user=yes’ 1.txt
#sed -ri ‘/^SELINUX=/cSELINUX=disabled ’ /etc/selinux/config
(替换整行c)
- 给文件添加注释
#Sed -r ‘2,6s/^/#/’ 1.txt 找到2到6行,把开始换成#
#sed -r ‘2,6s/(.*)/#\1/’ 1.txt
#sed -r ‘2,6s/.*/#&/’ 1.txt &匹配前面找到的内容
- 多个#换成一个#
以下三种情况会将全篇内容加上#
#sed -r ’30,50s/^[ \t]*#*/#/’ 1.txt
#sed -r ‘2,8 s/^[ \t#]*/#/’ a.txt
以下三种情况只会讲存在#开头的行替换为一个#
#sed -r ‘s/^#+/#/g’ 1.txt
#sed -r ’30,50s/^[ \t]*#+/#/’ 1.txt
#sed -r ‘2,8 s/^[ \t#]+/#/’ a.txt (空格就会注释)
- sed中使用外部变量
#var=111
#sed -r “1a$var” /etc/hosts 第一行后面追加变量111
追加变量:#sed -ri “$a$var” /etc/hosts
$a最后一行会被误认为是变量
故修改为#sed -r “\$a$var” /etc/hosts
暂存空间:hHGgx
#sed -r ‘1h;$G’ passwd
第一行覆盖到暂存空间,将暂存空间的内容追加到最后一行
#sed -r ‘1h;2G;3G;$G’ passwd
第一行覆盖到暂存空间,在2,3,最后一行追加到最后一行
#sed -r ‘1{h;d}’;$G’ passwd
第一行进入暂存空间,第一行在模式空间中删除,将暂存空间追加到最后一行
#sed -r ‘1h;2,$g’ passwd
第一行进入暂存空间,将暂存空间覆盖在2到最后一行
#sed -r ‘1h;2,3H;$G’ passwd
第一行进入暂存空间,将2,3行追加到暂存空间,将暂存空间的内容追加到最后一行
#sed -r ‘4h;5x;6G’ passwd
第四行进入暂存空间,将模式空间的第五行和暂存空间互换,将暂存空间的内容追加到第六行
#sed -r ‘1!G;$!h;$!d’ passwd
将passwd中内容倒叙输出
#awk -F”%” ‘{print $1}’ 文件名
#awk $0 默认全行
$1 $2 $3………$n (每个字段存储在已编号的变量中从$1开始)
#awk -F: ‘{print $1,$3}’ /etc/passwd
=awk ‘BEGIN { FS=”:”}{print $1}’ /etc/passwd 指定分割符为“ :”
切两次提取登录shell:
#awk -F: ‘BEGIN{ FS=”:”}{print $7}’ /etc/passwd | awk ‘BEGIN{FS=”/”}{print $3}’
OFS:输出字段分割符(默认是空格)用逗号分割是为了调用分割符空格
#awk -F: ‘BEGIN{FS=”:” ; OFS=”+++”}{print $1,$2,$3}’ /etc/passwd
RS:输入记录行分隔符,默认换行符
#awk ‘BEGIN{RS=” ”}{print $0}’ 文件名称
[root@localhost ~]# awk '{print $0}' a.txt
111 222 333 444 555:666:777
[root@localhost ~]# awk 'BEGIN{RS=" "}{print $0}' a.txt
111
222
333
444
555:666:777
请注意,在此时记录已经不是行的概念了。分隔符由”换行符“换成了”空格“
ORS:输出记录行分隔符,默认换行符(将换行符换成其他符号)
FNR:多文件独立编号(1~5,1~5)
#awk ‘{print FNR,$0}’ 1.txt 2.txt
NR:多文件汇总编号(1~10)
#awk ‘{print NR,$0}’ 1.txt 2.txt
NF:字段总数
#awk -F: ‘{print $NF}’ passwd 输出最后一列
#awk -F: ‘{print $(NF-1)}’ passwd 输出倒数第二列
Print函数:(默认不会在行尾自动换行,加\n)
#date | awk ‘{print “Month:” $2 “\nYear:”$1}’
Printf 制表函数
#awk -F: ‘{print “|%-15s|%-10s|%-15s|\n”,$1,$2,$3}’ /etc/passwd |head
%s:字符类型
%d:数值类型
%f:浮点型可以定义保留
-:表示左对齐,默认是右对齐
,:逗号是输出字段分隔符
正则表达式:(匹配行)
字符串比较
#awk ‘/^root/’ /etc/passwd
#awk ‘$0 ~/^root/’ /etc/passwd
#awk ‘$0 !~/^root/’ /etc/passwd
关系运算符:
#awk -F: ‘$3==0’ /etc/passwd
#awk -F: ‘$3<10’ /etc/passwd
#awk -F: ‘$7==”/bin/bash”’ /etc/passwd
算数运算:(语法:+,-,*,/,%取余,^幂)
示例:awk -F: ‘$3*10>500’ /etc/passwd
多条件:逻辑操作符和复合模式
语法:&&逻辑与
|| 逻辑或
!逻辑非
#awk -F: ‘$1 ~/root/ && $3<=15’ /etc/passwd
#awk -F: ‘$1 ~/root/ || $3<=15’ /etc/passwd
#awk -F: ‘!( $1 ~/root/ || $3<=15)’ /etc/passwd
范围模式:awk ‘/从哪里/,/到哪里/’ filename
(从adm到ldp,显示出来,实验时候注意避免重复的字段)
awk 调用变量
#自定义内部变量-v;
#awk -v user=root -F: ‘$1==user’ /etc/passwd
#外部变量
- 双引号
#var=”bash”
#echo “unix script” |awk “{print “123” ,\”$var\”}”
#echo “unix script” |awk “{print \$1 ,\”$var\”}”
输出123 bash
2.单引号
#var=”bash”
#echo “unix script” |awk ‘{print $1,”’”$var”’”}’
(使用单引号时,内部需要双引号转义)
条件&判断
1.If语句:格式{if (表达式) {语句;语句;……} }
需求:如果$3是0,就说他是管理员
#awk -F: ‘{if ($3==0) {print $1 “is 管理员”} }’ /etc/passwd
- if else 语句
格式:{if (表达式){语句;语句} else {语句} }
- 需求:如果第三列是0,打印该行第一列,否则打印第七列登录shell
#awk -F: ‘{if ($3==0) {print $1} else {print $7} }’ /etc/passwd
- 统计管理员和系统用户的数量
#awk -F: {if ($3==0) {count++} else {i++} } END {print “管理员个数:”count;print “系统用户数:” i } /etc/passwd
- if……else if……else
if (条件){动作}
else if (条件) {动作}
else {动作}
题目:显示出三种用户的信息
管理员的id为0,内置用户id<1000,普通用户id>999
#awk -F: ‘{if ($3==0) {print $1,”是管理员”} else if ($3>999) {print $1,”is user”} else {print $1,”is sofo user”}}’ /etc/passwd
统计三种用户的个数
#awk -F: ‘{if ($3==0) {i++} else if ($3>999) {k++} else {j++}} END {print “管理员个数:”i ;print “普通用户个数:”k;print “系统用户个数:”j}’ /etc/passwd
- 循环while
- 循环打印10个数字
#awk ‘BEGIN{while (i<=10) {print i ,i++} }’
(2) 第一行打印10次
#awk -F: ‘{while (i<=9) {print $0,i++} }’ passwd 没有初值,第十行不满足则跳出
(3)每行打印10次
#awk -F: ‘{i=1;while (i<=9) {print $0,i++}}’ passwd
定义数组:
- 将用户名定义为数组的值,打印第一个值
#awk -F: ‘{username[i++]=$1} END {print username[1] }’ passwd
- 数组遍历,按索引遍历
# awk -F: '{username[i++]=$1} END { for (i in username) {print i,username[i]}}' passwd
注意:第二个i可以取任意变量
3.查看最后一列登录shell
#awk -F: '{shell[$NF]++} END {for (i in shell) {print i,shell[i]}}' passwd
- 统计apache 日志中的访问前十
#cat access_log |awk ‘{ips[$1]++} END {for (i in ips ) {print i, ips[i] }} ’ |sort -k2 -rn |head
(-rn 从大到小,-k2按第二列数排序)