6.文本处理和正则表达式
作者:互联网
1. 文本编辑器vim
1.1 vim简介
1.1.1 基本格式
1.1.2 三种模式及转换
1.2 普通模式
1.3 编辑模式
1.4 命令行模式
2. 常见文本处理工具
2.1 查看文本内容
cat、hexdump、od、xxd
2.2 分页查看
more、less
2.3 查看前后行
head、tail
2.4 按列截取
cut
2.5 合并多个文件
paste
2.5 分析文本
wc、sort、uniq、diff、patch
3. 正则表达式
- 基本正则表达式:BRE,格式有时需要加转义字符
- 扩展正则表达式:ERE,格式可读性更强,推荐使用
3.1 正则表达式详解
3.1.1 字符匹配
-
匹配规则(基本正则和扩展正则没有区别)
. 匹配任意一个字符,可以是汉字 [] 匹配括号内任意一个字符 [^] 匹配不在括号内任意一个字符
-
范例
# . 匹配任意单个字符 [root@centos ~]# grep root /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [root@centos ~]# grep r..t /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin # [] 匹配括号内任意一个字符 [abc] abc中的任意一个字符,或的关系 [0-9] [a-z] [a-zA-Z] 数字 小写字母 大小写字母 # [^] 匹配不在括号内任意一个字符 [^abc] 除了abc的任意一个字符,非 # [.]表示真实的点 .[]表示任意字符 \.[]转义之后表示真实的点 [root@centos ~]# ls /etc | grep "rc[.0-6]" rc0.d rc1.d rc2.d rc3.d rc4.d rc5.d rc6.d rc.d rc.local [root@centos ~]# ls /etc | grep "rc[.0-6]." rc0.d rc1.d rc2.d rc3.d rc4.d rc5.d rc6.d rc.d rc.local [root@centos ~]# ls /etc | grep "rc[.0-6].." rc0.d rc1.d rc2.d rc3.d rc4.d rc5.d rc6.d rc.local [root@centos ~]# ls /etc | grep "rc[.0-6]\." rc0.d rc1.d rc2.d rc3.d rc4.d rc5.d rc6.d
-
不常用匹配规则
[:alnum:] 字母和数字 [:alpha:] 代表任何英文大小写字符,亦即 A-Z, a-z [:lower:] 小写字母,示例:[[:lower:]],相当于[a-z] [:upper:] 大写字母 [:blank:] 空白字符(空格和制表符) [:space:] 水平和垂直的空白字符(比[:blank:]包含的范围广) [:cntrl:] 不可打印的控制字符(退格、删除、警铃...) [:digit:] 十进制数字 [:xdigit:]十六进制数字 [:graph:] 可打印的非空白字符 [:print:] 可打印字符 [:punct:] 标点符号
3.1.2 匹配次数
-
匹配规则(扩展正则)
# 扩展正则 * 0次或任意次 .* 任意次的任意字符 ? 0或1次,有没有 + 至少一次,得有一个 {n} n次 {m,n} m次到n次 {,n} 最多n次 {m,} 最少m次 # 基本正则 \? 0或1次 \+ 至少一次 \{n\} n次 \{m,n\} m次到n次 \{,n\} 最多n次 \{n,\} 最少n次
-
范例
3.1.3 位置匹配
-
匹配规则
^ 行首 $ 行尾 \< 或 \b 词首 \> 或 \b 词尾
常用组合
^$ 空行 ^PATTERN$ 只包含PATTERN的整行 ^[[:space:]]*$ 包含任意个空白符的行 \<PATTERN\> 匹配一个单词(Linux中除了字符数字下划线,其余符号会导致分割成两个单词)
-
范例
# 过滤空白行和注释行 [root@centos ~]# grep -v -e "^$" -e "^#" /etc/profile
3.1.4 分组其他
-
匹配规则
# 扩展正则 () 分组 \1, \2, ... 引用第一组,第二组 ... | 或者 # 基本正则 \(\) 分组 \1, \2, ... 引用第一组,第二组 ... \| 或者
常用组合
a|b #a或b C|cat #C或cat (C|c)at #Cat或cat
-
范例
# 过滤空白行和注释行,三种效果一样,推荐第三种 #[root@centos ~]# grep -E -v "(^$)|(^#)" /etc/profile #[root@centos ~]# grep -E -v "^$|^#" /etc/profile [root@centos ~]# grep -E -v "^($|#)" /etc/profile # 第四种,^[]表示有一个字符排除空行,^#表示这个字符不是#排除注释 [root@centos ~]# grep -E "^[^#]" /etc/profile # 查找行首行尾单词相同的行 [root@centos ~]# grep -E "^(.*)\>.*\<\1$" /etc/passwd sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt
4. 文本处理三剑客
4.1 行过滤grep
-
格式:
grep [OPTION] PATTERN [FILE]
-
常见选项
-F 不支持正则表达式,相当于fgrep -E 使用扩展正则表达式,相当于egrep -v 显示不匹配的行 -i 忽略字符大小写 -n 显示行号 -c 统计匹配的行数 -o 仅显示匹配到的字符串 -w 匹配整个单词 -e 连接多个匹配条件(或者关系) -C # context, 显示前后各#行 -m NUM 匹配NUM次就不再进行搜索
-
常见选项举例
-v
: 显示不匹配的行-v
: 显示不匹配的行[root@centos ~]# grep -i Root /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin
-n
: 显示行号[root@centos ~]# grep -n root /etc/passwd 1:root:x:0:0:root:/root:/bin/bash 10:operator:x:11:0:operator:/root:/sbin/nologin
-c
: 统计匹配的行数[root@centos ~]# grep -c root /etc/passwd 2
-o
: 仅显示匹配到的字符串[root@centos ~]# grep -o root /etc/passwd root root root root
-w
: 匹配整个单词[root@centos ~]# grep -w roo /etc/passwd [root@centos ~]# grep roo /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin
-e
:连接多个匹配条件(或者关系)[root@centos ~]# grep -e root -e sync /etc/passwd root:x:0:0:root:/root:/bin/bash sync:x:5:0:sync:/sbin:/bin/sync operator:x:11:0:operator:/root:/sbin/nologin
-C NUM context
,显示前后各NUM行[root@centos ~]# grep -C 1 root /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin -- mail:x:8:12:mail:/var/spool/mail:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin
-m NUM
:匹配NUM次就不再进行搜索[root@centos ~]# grep root /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [root@centos ~]# grep -m 1 root /etc/passwd root:x:0:0:root:/root:/bin/bash
-
不常用选项
-q 静默模式,不输出任何信息 -f file 根据模式文件处理 -A # after, 显示后#行 -B # before, 显示前#行 -r 递归目录(即对子目录文件也使用grep),但不处理软链接 -R 递归目录,但处理软链接 --color=auto 对匹配到的文本着色显示
-
范例
# 取分区利用率最大值 [root@centos ~]# df | grep "/dev/sd" | tr -s ' ' % | cut -d "%" -f 5|sort -n |head -1 # 查询连接次数最多的 [root@centos ~]# ss -nt | grep "^ESTAB" | tr -s ' ' :|cut -d ':' -f 6|sort | uniq -c | sort -nr | head -1 2 172.32.115.1
4.2 行操作sed
-
基本格式:
sed [OPTION] '[script1][script2]' [input-file]
其中
[script1]
用于指定范围,[script2]
为操作
4.2.1 常见选项
-
[OPTION]
-n 不输出模式空间内容到屏幕,即不自动打印 -e 多点编辑 -f /PATH/SCRIPT_FILE 从指定文件中读取编辑脚本 -r, -E 使用扩展正则表达式 -i.bak 备份文件并原处编辑
-
范例:
sed ''
打印 和'[script1][p]'
打印# 可以认为sed中有两种打印的方法:sed '' 和 '[script1][p]'打印 # sed '',不加任何参数,全文打印 [root@centos ~]# sed '' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin # '[script1][p]'打印,[script1]不指定,全文打印 [root@centos ~]# sed -n 'p' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin # sed '' 和 '[script1][p]' 都使用时会造成重复打印 [root@centos ~]# sed 'p' /etc/passwd root:x:0:0:root:/root:/bin/bash root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin # '[script1][p]',仅打印[script1]指定的行,不关闭sed ''打印 [root@centos ~]# sed '1p' /etc/passwd root:x:0:0:root:/root:/bin/bash root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin # '[script1][p]',仅打印[script1]指定的行,关闭sed ''打印 [root@centos ~]# sed -n '1p' /etc/passwd root:x:0:0:root:/root:/bin/bash
4.2.2 [script1]:地址范围
-
[][script2]
:不指定地址,全文操作# '[script1][p]'打印,[script1]不指定,全文打印 [root@centos ~]# sed -n 'p' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin
-
[N][script2]
:单行指定,单行操作[root@centos ~]# sed -n '1p' /etc/passwd root:x:0:0:root:/root:/bin/bash [root@centos ~]# sed -n '3p' /etc/passwd daemon:x:2:2:daemon:/sbin:/sbin/nologin # $表示最后一行 [root@centos ~]# sed -n '$p' /etc/passwd demo:x:1001:501::/home/zk:/bin/bash
-
[/PATTERN/][script2]
:正则匹配,操作匹配/PATTERN/
的行[root@centos ~]# sed -n '/root/p' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [root@centos ~]# sed -n '/^root/p' /etc/passwd root:x:0:0:root:/root:/bin/bash
-
[m,n][script2]
:范围匹配,操作[m,n]
范围的行# [m,n] [root@centos ~]# sed -n '1,3p' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin # [m,+n] [root@centos ~]# sed -n '1,+1p' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin
-
[/PATTERN1/,/PATTERN2/][script2]
:正则范围匹配,操作[/PATTERN1/,/PATTERN2/]
范围的行注意:可用于查找指定时间段的日志,要避免因为
/PATTERN2/
不存在而导致全文操作[root@centos ~]# sed -n '/^root/,/^daemon/p' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin # 查找指定时间段的日志 [root@centos ~]# sed -n '/2020-06-20/,/2020-06-21/p' /data/access.log # 造成全文操作的分析 # /^root/匹配时开始,/^aaa/匹配时停止 # /^root/匹配后,下一行不是/^aaa/,不停止,一直操作到文本结束 [root@centos ~]# sed -n '/^root/,/^aaa/p' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin
-
[m~n][script2]
:步长匹配,m为起始行,n为指定步长# [1~2] 操作奇数行 [root@centos ~]# sed -n '1~2p' /etc/passwd root:x:0:0:root:/root:/bin/bash daemon:x:2:2:daemon:/sbin:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin # [2~2] 操作偶数行 [root@centos ~]# sed -n '2~2p' /etc/passwd bin:x:1:1:bin:/bin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin
4.2.3 [script2]:操作命令
-
'[p]'
:打印匹配的行[root@centos ~]# sed '1p' file.txt num1=20 num1=20 num2=18 num3=33
-
'[d]'
:删除指定的行(不指定参数sed -i
时,只是内存删除,不操作源文件)# 内存删除指定行,不指定-i [root@centos ~]# sed '1d' file.txt num2=18 num3=33 # 源文件不变 [root@centos ~]# cat file.txt num1=20 num2=18 num3=33
-
'[a]' \STRING
:在下一行添加STRING,支持使用\n实现多行追加
'[i]' \STRING
:在上一行添加STRING
'[c]' \STRING
:在当前行替换为STRING# a后面的\的规则 # \ 表示光标移动到第一行,之后的\n表示光标移动到下一行 # \\ 表示第一行为空行 # \\n 表示第一行为空行,第二行为空行 # \STRING 表示第一行为STRING # \STRING\n 表示第一行为STRING,且光标移动到第二行,第二行为空行 # \STRING\nSTRING 表示第一行为STRING,且光标移动到第二行,第二行为STRING # \\ 表示第一行为空行 [root@centos ~]# sed '/^root/a\\' /etc/passwd root:x:0:0:root:/root:/bin/bash 空行空行空行空行空行空行空行空行空行 bin:x:1:1:bin:/bin:/sbin/nologin # \STRING 表示第一行为STRING [root@centos ~]# sed '/^root/a\STRING' /etc/passwd root:x:0:0:root:/root:/bin/bash STRING bin:x:1:1:bin:/bin:/sbin/nologin # \STRING\n 表示第一行为STRING,且光标移动到第二行 [root@centos ~]# sed '/^root/a\STRING\n' /etc/passwd root:x:0:0:root:/root:/bin/bash STRING 空行空行空行空行空行空行空行空行空行 bin:x:1:1:bin:/bin:/sbin/nologin # \STRING\n表示第一行为STRING第二行为n [root@centos ~]# sed '/^root/a\STRING\nSTRING' /etc/passwd root:x:0:0:root:/root:/bin/bash STRING STRING bin:x:1:1:bin:/bin:/sbin/nologin [root@centos ~]# sed '/^root/a\\n' /etc/passwd root:x:0:0:root:/root:/bin/bash 空行空行空行空行空行空行空行空行空行 空行空行空行空行空行空行空行空行空行 bin:x:1:1:bin:/bin:/sbin/nologin
-
[w] /PATH/FILENAME
:匹配结果保存到指定文件FILENAME中[root@centos ~]# sed -n '/^root/p' /etc/passwd root:x:0:0:root:/root:/bin/bash [root@centos ~]# sed -n '/^root/w demo.txt' /etc/passwd [root@centos ~]# cat demo.txt root:x:0:0:root:/root:/bin/bash
-
[r] /PATH/FILENAME
:读取FILENAME中的文件内容到匹配结果的下一行[root@centos ~]# sed '/^root/r demo.txt' /etc/passwd root:x:0:0:root:/root:/bin/bash root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin
-
[=]
:显示行号# 不实用,行号显示不在同一行 [root@centos ~]# sed '/^root/=' /etc/passwd 1 root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin
-
[!script2]
:不匹配的行# 显示所有非#开头的行 [root@centos ~]# sed -n '/^#/!p' /root/.bash_profile
-
[s]/PATTERN/STRING/
:搜索替代# 每行首个匹配替换 [root@centos ~]# sed -n 's/root/admin/p' passwd admin:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/admin:/sbin/nologin # 全局替换 '[s]/PATTERN/STRING/[g]' [root@centos ~]# sed -n 's/root/admin/gp' passwd admin:x:0:0:admin:/admin:/bin/bash operator:x:11:0:operator:/admin:/sbin/nologin # 匹配行替换 '[script1][s]/PATTERN/STRING/' [root@centos ~]# sed -nr '/^r..t/s/r..t/SSSSS/gp' passwd SSSSS:x:0:0:SSSSS:/SSSSS:/bin/bash [root@centos ~]# grep -n 'r..t' passwd 1:root:x:0:0:root:/root:/bin/bash 10:operator:x:11:0:operator:/root:/sbin/nologin 12:ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin # 支持分组与后向引用, 注意使用扩展正则参数-r [root@centos ~]# sed -nr 's/(r..t)/\1ER/gp' passwd rootER:x:0:0:rootER:/rootER:/bin/bash operator:x:11:0:operator:/rootER:/sbin/nologin ftp:x:14:50:FTP User:/var/ftERp:/sbin/nologin
范例:取IP
[root@centos ~]# ifconfig enp0s8 | sed -nr '2s/.*inet (.*) netmask.*/\1/p' 172.32.115.11
范例:修改网卡名称
#查看配置 [root@centos ~]# sed -nr '/^GRUB_CMDLINE_LINUX=/p' /etc/default/grub GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet" #修改配置,-nr换未-ri.bak [root@centos ~]# sed -nr '/^GRUB_CMDLINE_LINUX=/s/"$/ net.ifnames=0"/p' /etc/default/grub GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap rhgb quiet net.ifnames=0" # 加载配置 [root@centos ~]# grub2-mkconfig -o /boot/grub2/grub.cfg # 重启生效
范例:非#开头的行加#,删除所有#行的#
# 查看原文件 [root@centos ~]# cat /etc/fstab # # /etc/fstab # Created by anaconda on Tue Aug 4 18:50:45 2020 # # Accessible filesystems, by reference, are maintained under '/dev/disk' # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info # /dev/mapper/centos-root / xfs defaults 0 0 UUID=1966b747-5b79-47de-b12b-6102f16f7764 /boot xfs defaults 0 0 /dev/mapper/centos-swap swap swap defaults 0 0 # 加#方式一,会漏掉空行,即空行加不上# [root@centos ~]# sed -rn 's/^[^#](.*)/#\1/p' /etc/fstab #dev/mapper/centos-root / xfs defaults 0 0 #UID=1966b747-5b79-47de-b12b-6102f16f7764 /boot xfs defaults 0 0 #dev/mapper/centos-swap swap swap defaults 0 0 # 加#方式一,空行也会加上# [root@centos ~]# sed -rn '/^#/!s@^@#@p' /etc/fstab # #/dev/mapper/centos-root / xfs defaults 0 0 #UUID=1966b747-5b79-47de-b12b-6102f16f7764 /boot xfs defaults 0 0 #/dev/mapper/centos-swap swap swap defaults 0 0 # 删除所有#行的# [root@centos ~]# sed -rn '/^#/s/^#//p' /etc/fstab /etc/fstab Created by anaconda on Tue Aug 4 18:50:45 2020 Accessible filesystems, by reference, are maintained under '/dev/disk' See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info [root@centos ~]#
范例:取目录名与基名
# 取目录名 [root@centos ~]# echo /etc/sysconfig/ | sed -rn 's#(.*)/([^/]+)/?#\1#p' /etc # 取基名 [root@centos ~]# echo /etc/sysconfig/ | sed -rn 's#(.*)/([^/]+)/?#\2#p' sysconfig
范例:引用变量生成随机文件名
# 注意使用双引号 [root@centos ~]# echo|sed "s/^/$RANDOM.log/" 24700.log [root@centos ~]# echo|sed "s/^/$RANDOM.log/" 1994.log # 或者使用三个单引号 [root@centos ~]# echo|sed 's/^/'''$RANDOM'''.log/' 10244.log
4.2.4 高级用法
-
常见参数
P 打印模式空间开端至\n内容,并追加到默认输出之前 h 把模式空间中的内容覆盖至保持空间中 H 把模式空间中的内容追加至保持空间中 g 从保持空间取出数据覆盖至模式空间 G 从保持空间取出内容追加至模式空间 x 把模式空间中的内容与保持空间中的内容进行互换 n 读取匹配到的行的下一行覆盖至模式空间 N 读取匹配到的行的下一行追加至模式空间 d 删除模式空间中的行 D 如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并不会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间不包含换行符,则会像发出d命令那样启动正常的新循环
-
范例
sed -n 'n;p' FILE sed '1!G;h;$!d' FILE sed ‘N;D’FILE seq 10 |sed '3h;9G;9!d' sed '$!N;$!D' FILE sed '$!d' FILE sed ‘G’ FILE sed ‘g’ FILE sed ‘/^$/d;G’ FILE sed 'n;d' FILE sed -n '1!G;h;$p' FILE
-
练习
1、删除centos7系统/etc/grub2.cfg文件中所有以空白开头的行行首的空白字符 2、删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字符 3、在centos6系统/root/install.log每一行行首增加#号 4、在/etc/fstab文件中不以#开头的行的行首增加#号 5、处理/etc/fstab路径,使用sed命令取出其目录名和基名 6、利用sed 取出ifconfig命令中本机的IPv4地址 7、统计centos安装光盘中Package目录下的所有rpm文件的以.分隔倒数第二个字段的重复次数 8、统计/etc/init.d/functions文件中每个单词的出现次数,并排序(用grep和sed两种方法分别实现) 9、将文本文件的n和n+1行合并为一行,n为奇数行
标签:bin,sbin,centos,正则表达式,文本处理,etc,sed,root 来源: https://www.cnblogs.com/is-raining/p/16641493.html