命令三剑客grep、sed、awk ;expect命令
三剑客命令的共性:
1、都支持正则表达式
2、都支持管道
echo 123 | passwd egon --stdin
正则表达式
PS:注意正则的特殊符号和元字符的区别!!!
什么是正则表达式?
是一种匹配规则:可以理解成筛子,这个筛子有设定的规则
特殊符号:
^ 以...开头
$ 以...结尾
PS:默认是从头一行行去匹配正则,对上之后还会在此行继续匹配
如果加上^ 或者 $ ,就只在头或者尾匹配,对上也不会在这一行继续匹配了
. 匹配任意一个字符 grep "a.c" w.txt
* 左边的那个字符出现0次或无穷次
.* 匹配没有或者所有
.*? 把贪婪的.*变成非贪婪 PS:要用perl正则,即配合grep ‐P使用
[] 匹配指定范围内的一个字符
[+‐*/] 此时‐无意义,需要写成[‐+*/]
如果[^] 这个^是取反
PS:不要和元字符[!]混淆了
[a‐zA‐Z]
PS:不要和元字符[a‐Z]混淆
+ 左边那个字符出现1次或无穷次
一 grep 过滤内容
语法
grep 选项 '规则(正则)'文件路径
grep的执行原理
========用法1
grep "root" /etc/passwd
# 打开文件,每读一行,都用正则表达式去匹配一下,但凡匹配成功一次,该行就被过滤出来的
root:x:0:0:root:/root:/bin/bash
========用法2
cat test.txt | grep "root"
ps aux | grep ssh
grep的选项
-n 显示行号,即将过滤出的内容在该文件的行号显示出来
-q 静默输出,主要作用在写脚本的时候不想在终端输出
--color
-i 忽略大小写
‐o 只显示过滤内容
‐oP 用于只过滤需要的内容
‐P perl的正则表达式语法,perl的正则更加多元化,能实现更加复杂的场景
‐l 如果匹配成功,则只将文件名/文件路径 打印出来,不成功则不打印 7 作用:确定文件中有没有需要的内容
‐r ‐R 递归 通常和‐l一起使用 9 作用:扫描检查目录中所有子目录子文件含有正则的文件
-A 2 后两行
-B 2 前两行
-C 2 前后两行
-c 统计过滤成功的行数
-v 过滤出不包含指定内容的行,取反
-w 过滤只包含具体单词的行
‐E 等同于 egrep 支持扩展正则
grep -rl "location" /etc/
正则表达式
案例1
grep -n "^root" /etc/passwd
grep -n "bash$" /etc/passwd
案例2
. 匹配任意一个字符
* 左边那个字符出现0次或无穷次
.* 匹配没有或者所有
.*? 非贪婪匹配(需要配合grep -P选项才可以使用)
# 例1
[root@www1 ~]# cat c.txt
abc
a+c
a-c
a1c
aaaaaaaaaaaaaaaac
bbbbbbbbc
cccc
dddd
[root@www1 ~]# grep "a.c" c.txt
abc
a+c
a-c
a1c
aaaaaaaaaaaaaaaac
# 例2
[root@www1 ~]# cat d.txt
a
ab
abbcccc
abbbbbbbbbbbbbbbbccc
bbbbbbbbbbbbb
aaaaaaaaaaaaaaaab
[root@www1 ~]# grep "ab*" d.txt
a
ab
abbcccc
abbbbbbbbbbbbbbbbccc
aaaaaaaaaaaaaaaab
# 例3:
[root@www1 ~]# cat e.txt
a123123213c3123123c
ac
a=-*(0c
cccccca123123c
[root@www1 ~]# grep "a.*c" e.txt
a123123213c3123123c
ac
a=-*(0c
cccccca123123c
# 例4:
[root@www1 ~]# cat f.txt
<a href="http://www.baidu.com">我是百度</a><a href="http://www.sina.com.cn">新浪</a>
1111
2222
3333
[root@www1 ~]# grep '".*"' f.txt
<a href="http://www.baidu.com">我是百度</a><a href="http://www.sina.com.cn">新浪</a>
[root@www1 ~]# grep -P '".*?"' f.txt
<a href="http://www.baidu.com">我是百度</a><a href="http://www.sina.com.cn">新浪</a>
[root@www1 ~]# grep -oP '".*?"' f.txt
"http://www.baidu.com"
"http://www.sina.com.cn"
案例3
[] 匹配指定范围的任意一个字符
[a1cd2]
[0-9]
[a-z]
# 例1
[root@www1 ~]# cat h.txt
abc
aBc
a1c
a2c
[root@www1 ~]# grep 'a[a-z]c' h.txt
abc
[root@www1 ~]# grep 'a[A-Z]c' h.txt
aBc
[root@www1 ~]# grep 'a[a-zA-Z]c' h.txt
abc
aBc
[root@www1 ~]# grep 'a[0-9]c' h.txt
a1c
a2c
# 例2
[root@www1 ~]# cat i.txt
a+c
a-c
a*c
a/c
a1c
a2c
[root@www1 ~]# grep 'a[+-*/]c' i.txt
grep: Invalid range end
[root@www1 ~]# grep 'a[+\-*/]c' i.txt
grep: Invalid range end
[root@www1 ~]# grep 'a[+*/-]c' i.txt
a+c
a-c
a*c
a/c
[root@www1 ~]#
# 例3:
[root@www1 ~]# cat i.txt
a+c
a-c
a*c
a/c
a1c
a2c
a!c
[root@www1 ~]# grep 'a[!+*/-]c' i.txt
a+c
a-c
a*c
a/c
a!c
[root@www1 ~]# grep 'a[^!+*/-]c' i.txt
a1c
a2c
[root@www1 ~]#
[root@www1 ~]#
案例4
+ 左边那个字符出现1次或无穷次
ab*
ab+
# 例1
[root@www1 ~]# cat d.txt
a
ab
abbcccc
abbbbbbbbbbbbbbbbccc
bbbbbbbbbbbbb
aaaaaaaaaaaaaaaab
[root@www1 ~]# grep -n 'ab*' d.txt
1:a
2:ab
3:abbcccc
4:abbbbbbbbbbbbbbbbccc
6:aaaaaaaaaaaaaaaab
[root@www1 ~]# egrep -n 'ab+' d.txt
2:ab
3:abbcccc
4:abbbbbbbbbbbbbbbbccc
6:aaaaaaaaaaaaaaaab
[root@www1 ~]#
# 例2
[root@www1 scripts]# cat 14.sh
#!/bin/bash
while true
do
read -p "请输入您的年龄: " age
if [[ $age =~ ^[0-9]+$ ]];then
break
else
echo "必须输入数字小垃圾"
fi
done
echo "后续代码"
[root@www1 scripts]# chmod +x 14.sh
[root@www1 scripts]# ./14.sh
请输入您的年龄: asdf
必须输入数字小垃圾
请输入您的年龄: 123
后续代码
二 sed 流式编辑器
特点
sed vs vim
1、sed可以把处理文件的规则事先写好,然后用同一套规则编辑多个文件 而vim只能单个编辑
2、sed一次只读取一行内容到内存,而vim是一次性全部读取到内存
即:sed 可以同时处理多个文件 ; 可以处理大文件
选项
‐n 静默模式,取消默认输出
‐i 改变输出流向,把输出到屏幕的内容(规则处理的结果+默认输出的结果 )覆盖回文件
即:写回原文件,完成修改
‐r 启用扩展正则表达式
命令
p 打印行 sed -n '1,3p' a.txt sed -ni '1p' a.txt
d 删除行
i 在...前插入 sed '3i haha' a.txt
a 在...后插入 sed '3a hehe' a.txt
c 修改这一整行
s///gi s查找并替换,用一个字符替换另一个,与g连用,表示全局匹配替换
i 忽略大小写
PS:此时的/只是分隔符,可以换成任何特殊字符,如s###gi sed '1,3s/jay/JAY/gi' a.txt
PS:命令可以用;连接多条,一起执行
例:1d;2d;7d; 删除第1,2,7行
1d;4p 删除第1行,打印第4行
# 场景1:
定位到某一行,然后将该的某一部分给替换掉
sed -r "定位+操作" test.txt
sed -r "3s/egon/EGON/gi" test.txt
sed -r "3,5操作" test.txt
sed -r "1操作;3操作" test.txt
sed -r "/^[a-zA-Z]/s/egon/EGON/gi" test.txt
# 场景2:
定位到某一行,然后删除
sed -r "1,3d" new.txt
sed -r "/^[0-9]/d" new.txt
# 场景3:
定位到某一行,在改行后添加新的配置
sed -r "1a XXXXXXXXXXXXXXXX" new.txt
# 场景4:
定位到某一行,将整行修改掉
sed -r "1c XXXXXXXXXXXXXXXX" new.txt
场景1案例
[root@www1 ~]# cat new.txt
xxEgonxxxegonxxxxx
xxx123xxegonxxegonxxx
EgonxxxxdaxegonxxEGONxxx
xxxyyyyxxegonxxxEgOnxx
xxxzzzxxegonxxxxx
xxxhhhhhxxegonxxxxx
[root@www1 ~]# sed -r '3s/egon/666666/' new.txt
xxEgonxxxegonxxxxx
xxx123xxegonxxegonxxx
Egonxxxxdax666666xxEGONxxx
xxxyyyyxxegonxxxEgOnxx
xxxzzzxxegonxxxxx
xxxhhhhhxxegonxxxxx
[root@www1 ~]# sed -r '3s/egon/666666/i' new.txt
xxEgonxxxegonxxxxx
xxx123xxegonxxegonxxx
666666xxxxdaxegonxxEGONxxx
xxxyyyyxxegonxxxEgOnxx
xxxzzzxxegonxxxxx
xxxhhhhhxxegonxxxxx
[root@www1 ~]# sed -r '3s/egon/666666/gi' new.txt
xxEgonxxxegonxxxxx
xxx123xxegonxxegonxxx
666666xxxxdax666666xx666666xxx
xxxyyyyxxegonxxxEgOnxx
xxxzzzxxegonxxxxx
xxxhhhhhxxegonxxxxx
[root@www1 ~]# sed -ri '3s/egon/666666/gi' new.txt
[root@www1 ~]# vim new.txt
场景1案例
[root@www1 ~]# cat new.txt
xxEgonxxxegonxxxxx
xxx123xxegonxxegonxxx
EgonxxxxdaxegonxxEgOnxxx
xxxyyyyxxegonxxxEgOnxx
xxxzzzxxegonxxxxx
xxxhhhhhxxegonxxxxx
[root@www1 ~]# sed -r '3s/^egon/666/gi' new.txt
xxEgonxxxegonxxxxx
xxx123xxegonxxegonxxx
666xxxxdaxegonxxEgOnxxx
xxxyyyyxxegonxxxEgOnxx
xxxzzzxxegonxxxxx
xxxhhhhhxxegonxxxxx
[root@www1 ~]#
场景1案例
[root@www1 ~]# cat new.txt
xxEgonxxxegonxxxxx
xxx123xxegonxxegonxxx
EgonxxxxdaxegonxxEgOnxxx
xxxyyyyxxegonxxxEgOnxx
xxxzzzxxegonxxxxx
xxxhhhhhxxegonxxxxx
[root@www1 ~]# sed -r '3,5s/egon/666/gi' new.txt
xxEgonxxxegonxxxxx
xxx123xxegonxxegonxxx
666xxxxdax666xx666xxx
xxxyyyyxx666xxx666xx
xxxzzzxx666xxxxx
xxxhhhhhxxegonxxxxx
[root@www1 ~]# sed -r '3s/egon/666/gi;5s/egon/666/gi' new.txt
xxEgonxxxegonxxxxx
xxx123xxegonxxegonxxx
666xxxxdax666xx666xxx
xxxyyyyxxegonxxxEgOnxx
xxxzzzxx666xxxxx
xxxhhhhhxxegonxxxxx
三 awk 处理有格式有规律的文本
语法
awk 选项 '规则(pattern{action})' 文件路径
选项
‐F 指定分隔符,默认是空格(多个空格也是1个空格)
awk -F: '定位{}' 文件路径
awk -F: 'NR==3{print $1,$7}' /etc/passwd
awk -F: 'NR>3 && NR<5{print $0}' /etc/passwd awk会读取文件一行内容然后赋值给$0
awk -F: 'NR==3 || NR==5{print $1"-"$3}' /etc/ NR行号
awk -F: '/bash$/{print $1}' /etc/passwd
awk -F: '{print $(NF-1)}' /etc/passws 倒数第2段
获取ip地址
[root@www1 ~]# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 1.1.1.8 netmask 255.255.255.0 broadcast 1.1.1.255
inet6 fe80::20c:29ff:fea2:d75e prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:a2:d7:5e txqueuelen 1000 (Ethernet)
RX packets 51153 bytes 4323126 (4.1 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 59883 bytes 64679002 (61.6 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
[root@www1 ~]# ifconfig eth0 | awk 'NR==2{print $1}'
inet
[root@www1 ~]# ifconfig eth0 | awk 'NR==2{print $2}'
1.1.1.8
[root@www1 ~]# ip=`ifconfig eth0 | awk 'NR==2{print $2}'`
[root@www1 ~]# echo $ip
1.1.1.8
四 expect 将交互式命令变成非交互
yum install expect -y
原理:
在原地捕捉命令返回的交互信息,如果匹配上交互信息中包含的字符,就匹配成功
即代表交互信息被expect捕捉到了 6 expect会将答案往里面填充,就完成了交互
远程执行命令:
ssh root@1.1.1.2 hostname
发现需要输入yes,然后输入密码 11 即交互
PS:/root/.ssh/known_hosts存放连接主机的记录信息 删除后就又需要输yes了
综上,写一个远程执行命令的脚本
#!/bin/bash
expect << EOF
spawn ssh root@1.1.1.2 hostname
expect {
"yes/no" {send "yes\r";exp_continue}
"*assword" {send "1\n"}
}
expect eof
EOF
============================================================================
spawn是except自带的,用它提交的命令都归expect管理 15 exp_continue继续下一步
chmod +x 1.sh
./1.sh