正则表达的基础知识已经在上一节讲过,下面要讲的是正则表达的三个关键命令grep、sed、awk。
1)grep 用于过滤行信息
作用:查找打印找与关键词匹配的行
参数:-n 在输出匹配行及行号一起输出;-v 打印不符合要求的行(取反);-i 不区分大小写;-w 打印完整单词的行;-An 打印符合要求的行以及下面n行;-Bn 打印符合要求的行以及上面n行;-Cn 打印符合要求的行以及上下n行。
[root@centos7 ~]# grep -A2 'halt' /etc/passwd #把包含halt的行及其下面的两行输出
[root@centos7 ~]# grep -B2 'halt' /etc/passwd #把包含halt的行及其上面的两行输出
[root@centos7 ~]# grep -C2 'halt' /etc/passwd #把包含halt的行及其上下各两行输出
[root@centos7 ~]# grep -n 'root' /etc/passwd #过滤出带有root关键字的行及行号
[root@centos7 ~]# grep -v 'nologin' /etc/passwd #过滤不带有nologin的行
[root@centos7 ~]# grep '[0-9]' /etc/inittab #过滤出所有包含数字的行
[root@centos7 ~]# grep -v '[0-9]' /etc/inittab #过滤出所有不包含数字的行
[root@centos7 ~]# grep -v '^#' /etc/inittab #过滤出非#开头的行
[root@centos7 ~]# grep 'game$' /etc/inittab #过滤出以game结尾的行
[root@centos7 ~]# grep -v '^#' /etc/crontab |grep -v '^$' #去除所有空行和以#开头的行
2)sed 用于行文本的过滤和替换
sed是一种在线编辑器,一次处理一行文本内容。处理时,把当前处理的行存储在临时缓冲区中,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。
作用:过滤查询和修改替换文本内容
参数:-n 只有经过sed 特殊处理的那一行(或者动作)才会被列出来;-e 直接在命令列模式上进行 sed 的动作编辑;-f 直接将 sed 的动作写在一个文件内;-r sed 的动作支持的是延伸型正规表示法的语法;-i 直接修改读取的文件内容,不输出到终端。a 新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行);c 取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行;d 删除,因为是删除啊,所以 d 后面通常不接任何内容;i 插入修改, i 的后面可以接字串,而这些字串会是新的一行;p 列印,将某个选择的数据输出;s 替换取代,直接进行取代;g 选择全部内容。
删除:d命令
[root@centos7 ~]# sed '2d' app.txt #删除文件的第二行
[root@centos7 ~]# sed '2,$d' app.txt #删除文件的第二行到末尾所有行
[root@centos7 ~]# sed '$d' app.txt #删除文件的最后一行
[root@centos7 ~]# sed '/test/'d app.txt #删除文件所有包含test的行
替换:s命令
[root@centos7 ~]# sed 's/test/prod/g' app.txt #文件中所有test替换为prod,无g则替换每行第一个
[root@centos7 ~]# sed -n 's/^test/prod/p' app.txt #开头为test的行,把test替换为prod并输出
[root@centos7 ~]# sed -n 's/\(love\)able/\1rs/p' app.txt #所有loveable会被替换成lovers
[root@centos7 ~]# sed 's#you#your#g' app.txt # “#”在这里是分隔符,代替了默认的“/”
选定行范围:逗号
[root@centos7 ~]# sed -n '/test/,/chart/p' app.txt #输出所有在test和cheart范围内的行
[root@centos7 ~]# sed -n '6,/^test/p' app.txt #输出从第6行开始到以test开头行之间的所有行
[root@centos7 ~]# sed '/test/,/chart/s/$/test/' app.txt #test和west之间的行,末尾加上test
多点编辑:e命令
[root@centos7 ~]# sed -e '1,5d' -e 's/test/dev/' app.txt #删除1至5行,并用dev替换test
从文件读入:r命令
[root@centos7 ~]# sed '/test/r 1.txt' app.txt #匹配test行,在该行插入1.txt内容一起输出
写入文件:w命令
[root@centos7 ~]# sed -n '/test/w 1.txt' app.txt #在app.txt中所有包含test的行都被写入1.txt
追加命令:a命令
[root@centos7 ~]# sed '/^test/a\\--->this is app.txt' app.txt< #内容被追加到以test开头行后面
插入修改:i命令
[root@centos7 ~]# sed '2i love you' app.txt #在第2行插入love you
[root@centos7 ~]# sed -i 's/\$/\!/g' app.txt #将行尾的$替换为!
3)awk 过滤编辑文本
awk和sed一样是流式编辑器,它也是针对文档中的行来操作的,按行处理文本。awk比sed更加强大,它能做到sed能做到的,也能做更复杂的正则。
1 awk命令形式
awk [-F|-f|-v] ‘BEGIN{} //{command1; command2} END{}’ file
[-F|-f|-v] 大参数,-F指定分隔符,-f调用脚本,-v定义变量 var=value
' ' # 引用代码块
BEGIN #初始化代码块,主要是引用全局变量,设置FS分隔符
// # 匹配代码块,可以是字符串或正则表达式
{} # 命令代码块,包含一条或多条命令
; # 多条命令使用分号分隔
END # 结尾代码块,主要是进行最终计算或输出结尾摘要信息
2 特殊变量符
$0 # 表示整个当前行
$1 #每行第一个字段
NF #字段数量变量
NR #每行的记录号,多文件记录递增
FNR # 与NR类似,多文件记录不递增,每个文件都从1开始
\t # 制表符
\n # 换行符
FS # BEGIN时定义分隔符
RS # 输入记录分隔符, 默认为换行符
~ # 匹配,与==相比不是精确比较
!~ # 不匹配,不精确比较
== # 等于,必须全部相等,精确比较
!= # 不等于,精确比较
&& # 逻辑与
|| # 逻辑或
+ # 匹配时表示1个或1个以上
/[0-9][0-9]+/ # 两个或两个以上数字
/[0-9][0-9]*/ # 一个或一个以上数字
OFS # 输出字段分隔符, 默认也是空格
ORS # 输出记录分隔符,默认为换行符
-F'[:#/]' # 定义三个分隔符
3 awk 示例
截取文档中的某个段
[root@centos7 ~]# head -n2 /etc/passwd |awk -F ':' '{print $1}' #-F 是指定分隔符为:,默认以空格或tab为分隔符
[root@centos7 ~]# head -n2 test.txt |awk -F':' '{print $0}' #$0 是指输出整行
匹配字符或字符串
[root@centos7 ~]# awk '/oo/' app.txt #匹配字符oo
[root@centos7 ~]# awk -F ':' '$1 ~/oo/' app.txt #匹配第一个字段中的字符oo
[root@centos7 ~]# awk -F ':' '/ro/ {print $3} /te/ {print $3}' /etc/passwd #awk可以多次匹配
条件操作
awk中是可以用逻辑符号判断的,比如 ‘==’ 就是等于,也可以理解为 ‘精确匹配’ 另外也有 >, ‘>=, ‘<, ‘<=, ‘!= 等等,值得注意的是,在和数字比较时,若把比较的数字用双引号引起来后,那么awk不会认为是数字,而认为是字符,不加双引号则认为是数字。
[root@centos7 ~]# awk -F ':' '$3=="0"' /etc/passwd #匹配第三个字段带有字符0的行
[root@centos7 ~]# awk -F ':' '$3>=500' /etc/passwd #匹配第三个字段大于数字500的行
[root@centos7 ~]# awk -F ':' '$7!="/sbin/nologin"' /etc/passwd #匹配第七个字段不是nologin的行
[root@centos7 ~]# awk -F ':' '$3<$4' /etc/passwd #两个段之间进行逻辑比较
[root@centos7 ~]# awk -F ':' '$3>"5" && $3<"7"' /etc/passwd #同时满足两个匹配条件的行
[root@centos7 ~]# awk -F ':' '$3>"5" || $7=="/bin/bash"' /etc/passwd #满足其中一个条件的行
常用的变量
NF :用分隔符分隔后一共有多少段,NF是多少段,而$NF是最后一段的值
NR :行数行号
[root@centos7 ~]# head -n3 /etc/passwd | awk -F ':' '{print NF}' #输出总段数
[root@centos7 ~]# head -n3 /etc/passwd | awk -F ':' '{print $NF}' #输出最后一段的值
[root@centos7 ~]# head -n3 /etc/passwd | awk -F ':' '{print NR}' #输出行号
[root@centos7 ~]# awk 'NR>20' /etc/passwd #使用行号20作为判断条件
[root@centos7 ~]# awk -F ':' 'NR>20 && $1 ~ /ssh/' /etc/passwd #输出NR大于20且第一段有ssh的行
修改计算字段值
[root@centos7 ~]# head -n3 /etc/passwd |awk -F ':' '$1="root"' #前三行第一段修改为root输出
[root@centos7 ~]# head -n2 /etc/passwd |awk -F ':' '{$7=$3+$4; print $7}' #计算字段并赋值
[root@centos7 ~]# awk -F ':' '{(t=t+$3)}; END {print t}' /etc/passwd #$3字段计和
[root@centos7 ~]# awk -F ':' '{if ($1=="root") print $0}' /etc/passwd #输出$1为root的行
本节的内容都是基础,上面的命令示例,可以满足日常使用,若要更复杂强大的功能,可以到命令工具官网查看。尤其是awk,有专业的书籍介绍该命令工具。命令的熟悉是写脚本的前提,在写一个脚本前,首先要清楚命令各个命令的执行结果,配合判断循环语句,实现批量复杂的处理功能。
来源:oschina
链接:https://my.oschina.net/u/4323755/blog/4725366