什么是sed?
sed流式编辑器,一行行的处理命令,自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等
为何用sed?
sed 对比vim
1、sed可以把处理文件的规则先写好,然后用同一套规则编辑多个文件而vim只能一个个编辑 ===》用一套规则处理多个文件
2、 sed处理文件,一次只处理一行,及同一时间内存中只有文件的一行内容,所以无论文件多大,都不会对内存造成过大的压力 ====》用于处理大文件
如何用sed?
sed -选项 ‘规则’ 文件名(自带一个默认输出)
选项:
-n:取消默认输出
-i:将输出到屏幕中的结果(即规则处理的和默认输出的结果)覆盖到原文件当中 ps:调节完毕之后再使用此命令
-e 允许多项编辑
-r 支持扩展元字符
-f 指定sed脚本文件名
规则:定位+命令
定位方式:
没有定位的默认定位所有行,sed的两种定位方式1.可以用行号(数字)进行定位,2.可以用正则表达式进行定位
行号(数字)定位:利用数字来定位
示例:
sed ‘1p’ a.txt
输出结果:第一行被重复输出了遍到屏幕上(原理:将文件第一行内容输出到屏幕上,默认输出整个文件内容到屏幕上)
sed ‘1,3p’ a.txt
输出结果为:第一到三行都被重复输出到屏幕上 (原理:将文件第一行内容到第三行内容输出到屏幕上,默认输出整个文件内容到屏幕上)
sed ‘3;5p’ a.txt
输出结果为:第三行内容,第五行内容被重复输出到屏幕上(原理:将文件第三行内容,第五行内容输出到屏幕上,默认输出整个文件内容到屏幕上)
正则定位:两个左斜杠,斜杠中间是筛选条件
sed ‘/^egon/p’ a.txt
输出结果为:以egon开头的行重复打印一遍
命令:
a 在当前行后添加一行或多行
c 用新文本修改(替换)当前行中的文本
i 在当前行之前插入文本
l 会用$符号标识出文件中看不到的字符的位置
p:文件输出到屏幕
d:删除内存中的文件,通常输出结果为空
s:替换 用法:s/要替换的内容/替换的内容/(此处//为分隔符,也可以用其他符号做分隔符)
与s一起使用的是g和i
g 在行内进行全局替换
i 忽略大小写(跟s一起使用时)
n 把下一行内容读入模式空间(sed内置的一个缓冲区),后续的处理命令处理的都是刚读入的新内容
q 结束或退出sed,不会将后续内容读入模式空间
r 从文件中读
! 对所选行以外的所有行应用命令
w 将行写入文件
y 将字符转换为另一字符(不支持正则表达式),y/egon/1234/ e->1 g->2 o->3 n->4
案例:
打印命令:p
#打印a.txt文件中包含egon的行
sed -r "/egon/p" a.txt
#打印a.txt文件中包含egon的行,并显示其在文件中的对应行数
sed -r -n "/egon/p" a.txt
删除命令:d,注意用单引号
#删除第三行内容
sed -r '3d' a.txt
#删除第三行到文件末尾的行
sed -r '3,$d' a.txt
#删除文件中末尾的行
sed -r '$d' a.txt
#删除文件中包含egon的行
sed -r '/egon/d' a.txt
sed -r '1,/egon/{/egon/d}' a.txt # 只删除模式匹配成功的第一行
替换命令:s
#只匹配一个egon换为Bigegon
sed -r 's/egon/Bigegon/' a.txt
#将文中所有egon都替换成Bigegon
sed -r 's/egon/Bigegon/g' a.txt
#将文中以egon开头的行中的第一个egon换成Bigegon
sed -r 's/^egon/Bigegon/g' a.txt
将文件中的root换成egon
sed -r -n 's/root/egon/gip' /etc/passwd
sed -r 's/[0-9]$/&.change/' a.txt # &代表取到匹配成功的整行内容
sed -r 's/^([a-zA-Z]+)([^[a-zA-Z]+)/\2\1/' a.txt
sed -r 's#egon#bigegon#g' a.txt
多重编辑命令:e
sed -r -e '1,3d' -e 's/[Ee]gon/EGON/g' a.txt # 在前一个-e的基础之上进行第二个-e操作
sed -r '1,3d;s/[Ee]gon/EGON/g' a.txt
sed -r '3{s/[0-9]/x/g;s/[Ee]gon/EGON/g}' a.txt # 只处理第三行
sed -r '1,3{s/[0-9]/x/g;s/[Ee]gon/EGON/g}' a.txt # 处理1到3行
sed -r -n '1p;p' a.txt # ;分隔依次运行,先针对第一行进行p操作,再针对所有行进行p操作
sed -r -n '1{p;p}' a.txt # 只针对第一行,连续进行两次p操作
反向选择!
sed -r '3d' a.txt
sed -r '3!d' a.txt
读文件命令:r
sed -r '/^Egon/r b.txt' a.txt # 在匹配成功的行后添加文件b.txt的内容
sed -r '/2/r b.txt' a.txt # 在第2行后面添加文件b.txt的内容
写文件命令:w
sed -r '/[Ee]gon/w b.txt' a.txt # 将匹配成功的行写入新文件b.txt
sed -r '3,$w /root/new.txt' a.txt # 将第3行到最后一行写入/root/new.txt
追加命令:a
sed -r '2aXXXXXXXXXXXXXXXXXXXX' a.txt #在第2行后添加一行
sed -r '2a1111111111111\ # 可以用\续行
> 222222222222\
> 333333333333' a.txt
插入命令:i
sed -r '2i1111111111111' /etc/hosts
sed -r '2i111111111\
> 2222222222\
> 3333333333' a.txt
修改命令:c
sed -r '2c1111111111111' a.txt
sed -r '2c111111111111\
> 22222222222\
> 33333333333' a.txt
把下一行内容读入模式空间:n
# sed -r '/^Egon/{n;s/[0-9]/x/g}' a.txt # 将匹配/^Egon/成功的行的下一行读入模式空间进行s处理
[root@aliyun ~]# cat a.txt
/etc/egon/666
etc
[root@aliyun ~]# sed -r '\#/etc/egon/666#n;c 1111' a.txt
/etc/egon/666
1111
[root@aliyun ~]#
转换命令:y
# sed -r '1,3y/Eeo/12X/' a.txt # 1到3行进行转换 对应规则:a->1 e->2 o->X
退出:q
# sed -r '5q' a.txt
# sed -r '/[Ee]gon/{ s/[0-9]/X/; q; }' a.txt # 匹配成功/[Ee]gon/则执行{}内命令,q代表退出,即替换一次则退出,如果文件中多行符合规则的内容也只替换了第一个
拓展内容:
sed 有两个内置的存储空间:
模式空间(pattern space):
如你所知,模式空间用于 sed 执行的正常流程中。该空间 sed 内置的一个缓冲区,用来存放、修改从输入文件读取的内容。
保持空间(hold space):
保持空间是另外一个缓冲区,用来存放临时数据。Sed 可以在保持空间和模式空间交换数据,但是不能在保持空间上执行普通的 sed 命令。
每次循环读取数据过程中,模式空间的内容都会被清空,然而保持空间的内容则保持不变,不会在循环中被删除。
模式空间与保持空间的操作命令
x:命令x(exchange) 用于交换模式空间和保持空间的内容
h:模式空间复制/覆盖到保持空间
H:模式空间追加到保持空间
g:保持空间复制/覆盖到模式空间
G:保持空间追加到模式空间
n:读取下一行到/覆盖到模式空间
N:将下一行添加到模式空间
d:删除pattern space中的所有行,并读入下一新行到pattern space中
什么是AWK?
用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个 或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix 下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用
为何要使用awk?
(擅长处理有规律的文本文件,主要做一些格式化处理)
如何用AWK?
用法:
AWK -选项 ‘规则’ 文件路径 规则=定位+命令 命令要用花括号括起来,且规则必须用单引号引起来,双引号不行
AWK -F:’{print $1,$3}’ /etc/passwd
运行结果:将/etc/passwd文件中以:为分隔符的第一段,第三段打印出来
工作原理:
(1)awk会接收一行作为输入,并将这一行赋给awk的内部变量$0,每一行也可称为一个记录,行的边界是以换行符作为结束
(2)然后,刚刚读入的行被以:为分隔符分解成若干字段(或域),每个字段存储在已编号的变量中,编号从$1开始,最多达100个字段,注意:如果未指定行分隔符,awk将使用内置变量FS的值作为默认的行分隔符,FS默认值为空格
(3)**使用print函数打印,如果$1$3之间没有逗号,它俩在输出时将贴在一起,应该在$1,$3之间加逗号,**该逗号与awk的内置变量OFS保持一致,OFS默认为空格,于是以空格为分隔符输出$1和$3
我们可以指定:awk -F: ‘BEGIN{OFS="-"}{print $1,$3}’ /etc/passwd (以-为分隔符输出$1和$3)
(4)输出之后,将从文件中获取另一行,然后覆盖给$0,继续(2)的步骤将该行内容分隔成字段。。。继续(3)的步骤
该过程一直持续到所有行处理完毕
选项:
-F:指定分隔符,指定空格为分隔符时,需要将空格用引号引起来。
定位:
行号定位:
NR == 1
记录与字段相关的内部变量
$0: 输出整行内容
NR: 记录号,每处理一条记录,NR的值加1(也可作为指定行号的指令来用)
NF: 保存记录的字段数,最大为100
FS:输入字段分隔符,(也就是指定什么符号为分隔符进行处理)
OFS:输出字段分隔符,(指定什么符号作为处理结果的分隔符 也可简写成 -F ,若指定空格为分隔符时,需用引号引起来)
格式化输出:
==============print函数===================
[root@egon ~]# date | awk '{print "月:",$2,"\n年:",$1}'
月: 09月
年: 2020年
[root@egon ~]#
[root@egon ~]# awk -F: '{print "用户名:",$1,"用户id:",$3}' /etc/passwd
================printf函数===================
[root@egon ~]# awk -F: '{printf "用户名:%s 用户id:%s\n",$1,$3}' /etc/passwd
[root@egon ~]# awk -F: '{printf "|%-15s| %-10s| %-15s|\n", $1,$2,$3}' /etc/passwd
%s 字符类型
%d 数值类型
占15格的字符串
- 表示左对齐,默认是右对齐
printf默认不会在行尾自动换行,加\n
示例:
awk '/west/' datafile
awk '/^north/' datafile
awk '/^(no|so)/' datafile
awk '{print $3,$2}' datafile
awk '{print $3 $2}' datafile
awk '{print $0}' datafile
awk '{print "Number of fields: "NF}' datafile
awk '/northeast/{print $3,$2}' datafile
awk '/E/' datafile
awk '/^[ns]/{print $1}' datafile
awk '$5 ~ /\.[7-9]+/' datafile
awk '$2 !~ /E/{print $1,$2}' datafile
awk '$3 ~ /^Joel/{print $3 " is a nice guy."}' datafile
awk '$8 ~ /[0-9][0-9]$/{print $8}' datafile
awk '$4 ~ /Chin$/{print "The price is $" $8 "."}' datafile
awk '/Tj/{print $0}' datafile
awk '{print $1}' datafile2
awk -F: '{print $1}' datafile2
awk '{print "Number of fields: "NF}' datafile2
awk -F: '{print "Number of fields: "NF}' datafile2
awk -F"[ :]" '{print $1,$2}' datafile2
awk '$7 == 5' datafile
awk '$2 == "CT" {print $1, $2}' datafile
awk '$7 != 5' datafile
awk '$7 < 5 {print $4, $7}' datafile
awk '$6 > .9 {print $1,$6}' datafile
awk '$8 <= 17 {print $8}' datafile
awk '$8 >= 17 {print $8}' datafile
awk '$8 > 10 && $8 < 17' datafile
awk '$2 == "NW" || $1 ~ /south/ {print $1, $2}' datafile
awk '!($8 == 13){print $8}' datafile
awk '/southem/{print $5 + 10}' datafile
awk '/southem/{print $8 + 10}' datafile
awk '/southem/{print $5 + 10.56}' datafile
awk '/southem/{print $8 - 10}' datafile
awk '/southem/{print $8 / 2 }' datafile
awk '/southem/{print $8 / 3 }' datafile
awk '/southem/{print $8 * 2 }' datafile
awk '/southem/{print $8 % 2 }' datafile
awk '$3 ~ /^Suan/ {print "Percentage: "$6 + .2 " Volume: " $8}' datafile
awk '/^western/,/^eastern/' datafile
awk '{print ($7 > 4 ? "high "$7 : "low "$7)}' datafile //条件运算符
awk '$3 == "Chris" {
$3 = "Christian"; print}' datafile //赋值运算符
awk '/Derek/ {
$8 += 12; print $8}' datafile //$8 += 12等价于$8 = $8 + 12
awk '{
$7 %= 3; print $7}' datafile //$7 %= 3等价于$7 = $7 % 3
grep命令主要用于过滤文本,grep家族如下
grep: 在文件中全局查找指定的正则表达式,并打印所有包含该表达式的行
egrep:扩展的egrep,支持更多的正则表达式元字符
fgrep:固定grep(fixed grep),有时也被称作快速(fast grep),它按字面解释所有的字符
原理:
grep打开文件,每读一行,都用正则表达式去匹配一次,但凡匹配成功一次,该行就被过滤出来
找到: # grep返回的退出状态为0
没找到: # grep返回的退出状态为1
找不到指定文件: # grep返回的退出状态为2
选项:
-n:–line-number 在过滤出的每一行前面加上他=它在文件中相对应的行号
-o --only-macthing 只显示匹配的内容
-i:–ignore-care 忽略大小写
–color: 加颜色(默认就是开启)
-q, --quiet, --silent 静默模式,没有任何输出,得用$?来判断执行成功没有,即有没有过滤到想要的内容,返回0为找到了,返回1没找到,返回2找不到指定文件
-l:–files-with-matches 如果匹配成功,则将文件名打印出来,失败则不打印通常-rl一起用
-r,-R:–recursive 递归
-A 2 后两行
-B 2 前两行
-C 2 前后两行
-v 取反,(只显示不匹配的行,也就是过滤掉grep的结果)
-c, --count 如果匹配成功,统计匹配到的行数
w 匹配单词
-P 匹配非贪婪的字符(一般与.*?连用)
-E 等于egrep,扩展
示例:
# 1、-n显示包含root的行,并显示其行数
[root@egon ~]# grep -n 'root' /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
10:operator:x:11:0:operator:/root:/sbin/nologin
[root@egon ~]#
# 2、-o只显示文件中匹配到的root
[root@egon ~]# grep -o 'root' /etc/passwd
root
root
root
root
[root@egon ~]#
# 3、-q 静默输出,输出结果不打印到屏幕上
[root@egon ~]# grep -q 'root' /etc/passwd
[root@egon ~]# echo $?
0
# 4、--color加颜色
[root@egon ~]# alias grep
alias grep='grep --color=auto'
[root@egon ~]#
# 5、-i过滤时忽略大小写
[root@egon ~]# echo "EGON" |grep -i egon
EGON
[root@egon ~]#
# 6、-A\-B\-C输出过滤到文件的后两行、前两行、前后两行
[root@egon ~]# grep -A 2 'root' /etc/passwd
[root@egon ~]# grep -B 2 'root' /etc/passwd
[root@egon ~]# grep -C 2 'root' /etc/passwd
# 7、-c统计次数
[root@egon ~]# grep -c 'root' /etc/passwd
2
[root@egon ~]#
# 8、-v反向查找只显示不匹配的内容
[root@egon ~]# ps aux | grep nginx |grep -v grep
[root@egon ~]#
[root@egon ~]# ps aux | grep [n]ginx
[root@egon ~]#
# 9、-w匹配单词
[root@egon ~]# netstat -an |grep -w 80
tcp6 0 0 :::80 :::* LISTEN
[root@egon ~]# netstat -an |grep '\<80\>'
tcp6 0 0 :::80 :::* LISTEN
[root@egon ~]# netstat -an |grep '\b80\b'
tcp6 0 0 :::80 :::* LISTEN
# 10、-rl
[root@egon ~]# grep -rl 'root' /etc # 将/etc目录下所有包含'root'内容的文件都列出来
ps aux : 查看系统上运行的进程
有上述代码可知grep也支持管道符号,即三剑客都支持管道符号,都支持正则表达式
kill -9 进程号:强制杀死一个进程
作业:
写一个脚本可以远程操作100台机器并改密码
[root@web02 ~]# cat gaimi.sh
#!/bin/bash
while read line
do
user=`echo $line | awk -F: '{print $1}'` #user
old_pwd=`echo $line | awk -F: '{print $2}'` #old password
new_pwd=`echo $line | awk -F: '{print $3}'` #new password
ip=`echo $line | awk -F: '{print $4}'` #ip
cmd=`echo $new_pwd | passwd --stdin root`
expect << EOF
spawn ssh $user@$ip $cmd
expect {
"yes/no" {send "yes\r";exp_continue}
"*assword" {send "$old_pwd\n"}
}
expect eof
EOF
done < passwd.txt