【Linux命令】《鸟哥Linux基础》第十一章 正则表达式与文件格式化处理
第十一章 正则表达式与文件格式化处理11.1 基础概念正则表达式是对字符串的处理的表示方式。11.2 基础正则表达式11.2.1 语系采用LANG=C的语系。特殊符号意义[:alnum:]英文大小写字符和数字 0-9 a-z A-Z[:alpha:]英文大小写字符 a-z A-Z[:blank:]代表空格键和Tab键两种空格符[:cntrl:]代表 键盘上面的控制按键,包括CR LF Tab De
·
第十一章 正则表达式与文件格式化处理
11.1 基础概念
正则表达式是对字符串的处理的表示方式。
11.2 基础正则表达式
11.2.1 语系
采用LANG=C
的语系。
特殊符号 | 意义 |
---|---|
[:alnum:] | 英文大小写字符和数字 0-9 a-z A-Z |
[:alpha:] | 英文大小写字符 a-z A-Z |
[:blank:] | 代表空格键和Tab键两种空格符 |
[:cntrl:] | 代表 键盘上面的控制按键,包括CR LF Tab Del 等 |
[:digit:] | 数字 0-9 |
[:graph:] | 除了空格符(空格键、Tab键)之外的其他所有按键 |
[:lower:] | 小写字母 a-z |
[:upper:] | 大写字母 A-Z |
[:print:] | 任何可以被打印出来的字符 |
[:punct:] | 标点符号 |
[:space:] | 任何会产生空白的字符,包括空格键、Tab键、CR等 |
[:xdigit:] | 十六进制数字,包括0-9 A-F a-f |
grep [-A] [-B] [--color=auto] '查找字符' filename
-A 后可接数字,为after的意思,除了列出该行之外,后续的n行也跟着列出
-B 后可接数字,为before的意思,除了列出该行之外,前面的n行也跟着列出
dmesg | grep -n 'tun' 从dmesg输出的所有内容中,将带有关键字tun的那行带行号显示
dmesg | grep -n -A3 -B 2 'tun' 同上,在此基础上,将前面的2行和后面的3行一起显示出来
11.2.3 基础正则表达式练习
调整语系:
export LANG=C
export LC_ALL=C
grep -n 'the' regular_express.txt 有the的行显示
grep -vn 'the' regular_express.txt 无the的行显示
grep -ni 'the' regular_express.txt 有不论大小写的the的行都显示
grep -n 't[ae]st' regular_express.txt 有test的和taste的行都会被显示出来,[ae]表示a或者e
grep -n '[^a-z]oo' regular_express.txt 字符串'oo'前面未出现小写字母的行都显示
grep -n '[^[:lower:]]oo' regular_express.txt 同上
grep -n '[0-9]' regular_express.txt 有数字的行都显示,
grep -n '[[:digit:]]' regular_express.txt 同上
grep -n '[0-9][0-9]*' regular_express.txt 同上,这是使用正则表达式匹配,上面使用通配符匹配
grep -n '^the' regular_express.txt 开头是the的行都显示
grep -n '^[a-z]' regular_express.txt 开头是小写字母的行都显示
grep -n '^[[:lower:]]' regular_express.txt 同上
grep -n '^[^a-zA-Z]' regular_express.txt 开头别是英文字母的行都显示
grep -n '^[^[:alpha:]]' regular_express.txt 同上
grep -n '\.$' regular_express.txt 行尾是小数点的行都显示
grep -n '^$' regular_express.txt 显示空白行,结果是22:
grep -n '^$' regular_express.txt | cat -A 显示空白行,并显示特殊字符,结果是22:$
grep -v '^$' /etc/rsyslog.conf | grep -v '^#' 空白行与开头是井号键的注释行都不显示
grep -n 'g..d' regular_express.txt 将g与d之间存在两个任意字符的那行显示
grep -n 'oo*' regular_express.txt 第一个o务必存在,后面的o*表示可以有0到无穷多个o
grep -n 'ooo*' regular_express.txt 含有两个或更多连续o的行显示
grep -n 'goo*g' regular_express.txt 字符串首尾都是g,且中间有1个以上的连续o,没有其他杂字符
grep -n 'g.*g' regular_express.txt 字符串首尾都是g就行,不管中间有啥有多少,都显示
grep -n 'o\{2\}' regular_express.txt 含有两个o的行显示
grep -n 'go\{2,5\}g' regular_express.txt 找到g后面接2-5个o,之后又有个g的行显示
grep -n 'go\{2,\}g' regular_express.txt 找到g后面接2个或2个以上的o,只有又有个g的行显示
^,在字符集合符号(中括号[])内外表示含义不同,在内表示反向选择,在外表示定位在行首。
Windows下的换行符是^M$ ,而Linux下的换行符是$。两者有别。
通配符*,代表任意字符,0个或多个;小数点.代表【一定有一个任意字符】;星号*代表【重复前一个字符,0到无穷多次】,是组合形态。
cat -An regular_express.txt |head -n 10 | tail -n 5 将第5-10行显示出来,带行号,且显示特殊字符
输出:
6 GNU is free air not free beer.$
7 Her hair is very beauty.$
8 I can't finish the test.$
9 Oh! The soup taste good.$
10 motorcycle is cheap than car.$
11.2.4 基础正则表达式字符集合
RE字符 | 意义 |
---|---|
^word | 带查找的字符串word在行首 |
word$ | 带查找的字符串word在行尾 |
小数点. | 一定有一个任意字符 |
\ | 转义符,将特殊符号的特殊意义去除 |
* | 重复0个到无穷多个的签一个RE字符 |
[list] | 字符集合的RE字符,里面列出想要选取的字符 |
[n1-n2] | 字符集合的RE字符,里面列出想要选取的字符范围 |
[^list] | 字符集合的RE字符,里面列出不要的字符串或范围 |
{n,m} | 连续n到m个的前一个RE字符;{n}是连续n个的前一个RE字符;{n,}连续n个以上的前一个RE字符 |
ls -l * 匹配任意文件
ls -l a* 匹配文件名开头是a的文件
ls | grep -n '^a.*' 匹配文件名开头是a的文件
ls -l /etc | grep '^l' 找到/etc下的链接文件【lrwxrwxrwx】开头是l
ls -l /etc | grep '^l'|wc -l 这样的文件总共有多少个,列出个数
11.2.5 sed工具
sed本身也是管道命令,可以分析标准输入。可以完成替换、删除、新增、选取特定行等功能。
sed [-nefr] [操作]
-n 安静模式,只有经过sed处理的行才显示到屏幕上
-e 直接在命令行模式上进行sed的操作编辑
-f 直接将sed的操作写在一个文件内,-f filename 可以执行filename内的sed操作
-r sed的操作使用的是扩展性正则表达式语法(默认是基础正则表达式语法)
-i 直接修改读取的文件内容,而不是由屏幕输出
操作:[n1[,n2]] function
n1,n2 未必存在,选择进行操作的行数
function包括: a 新增
c 替换
d 删除
i 插入
p 打印
s 替换
nl /etc/passwd | sed '2,5d' 删除2-5行后的内容显示在屏幕上
nl /etc/passwd | sed '2d' 删除第2行后的内容显示在屏幕上
nl /etc/passwd | sed '3,$d' 删除第3行到最后一行之后的内容显示在屏幕上
nl /etc/passwd | sed '/^$/d' 删除空白行
nl /etc/passwd | sed '2a drink tea' 即在第二行结束,第三行开头添加drink tea字样
nl /etc/passwd | sed '2i drink tea' 即在第二行前面,第一行后面添加drink tea字样
可以新增好几行数据,必须用转义字符+Enter键隔开:
nl /etc/passwd | sed '2a drink tea or \
> drink bear?'
替换整行:
nl /etc/passwd | sed '2,5c No 2-5 number' 将第2-5行数据替换成No 2-5 number
输出:
1 root:x:0:0:root:/root:/bin/bash
No 2-5 number
6 sync:x:5:0:sync:/sbin:/bin/sync
按行数输出整行内容:
nl /etc/passwd | sed -n '5,7p'
以行为单位,实现部分数据的查找和替换:
sed 's/要被替换的字符/新的字符/g'
sed 's/要被替换的字符//g' 将匹配到的字符串删除
cat /etc/man_db.conf | grep 'MAN'|sed 's/#.*$//g' 删除掉每一行注释之后的内容,原本的注释行都变成了空白行
cat /etc/man_db.conf | grep 'MAN'|sed 's/#.*$//g' | sed '/^$/d' 因此还得删除空白行
直接修改文件,将文件末尾的点换成感叹号:
sed -i 's/\.$/\!/g' regular_express.txt
直接修改文件,在文件末尾添加一句注释# This is a test
sed -i '$a # This is a test' regular_express.txt
11.3 扩展正则表达式
RE字符 | 意义 |
---|---|
+ | 重复1个或1个以上的前一个RE字符 |
? | 0个或1个的前一个RE字符 |
| | 用或(or)的方式找出数个字符串 |
() | 找出群组字符串 |
()+ | 多个重复群组的判别 |
11.4 文件的格式化与相关处理
11.4.1 格式化打印:printf
printf '打印格式' 实际内容
\a 警告声音输出
\b 退格键(backspace)
\f 清屏
\n 输出新行
\r 回车按键
\t 水平的Tab键
\v 垂直的Tab键
\xNN NN是两位数数字,可以转换数字成为字符
%ns 多少个字符
%ni 多少个整数位数
%N.nf 共要N个位数,其中小数点占n位
printf '%s\t %s\t %s\t %s\t \n' $(cat printf.txt) 要先把文件中的内容提取出来给printf用
printf '\x45\n' 看十六进制的数值45代表的字符是啥
11.4.2 awk:好用的数据处理工具
awk比较倾向于一行当中分成数个字段来处理,适合处理小型文本数据。
awk '条件类型1{操作1} 条件类型2{操作2} ...' filename 默认分隔符是空格键和Tab键
last -n 5 | awk '{print $1 "\t" $3}' 显示前5行中的第一字段和第三字段(awk最常用的功能)
last -n 5 | awk '{print $1 "\t lines:" NR "\t columns:" NF}' 输出字段1,目前处理的第几行NR,该行有几个字段NF
cat /etc/passwd | awk '{FS=":"} $3 < 10 {print $1 "\t" $3}' 将第3字段的UID号码小于10的那行的字段1和字段3显示出来(这种方式,第一行数据无法正确处理,那个时候的分隔符还是默认为空格)
cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t" $3}' 将第3字段的UID号码小于10的那行的字段1和字段3显示出来(解决上述问题)
变量名称 | 意义 |
---|---|
NF | 每一行($0)拥有的字段总数 |
NR | 目前awk所处理的是第几行数据 |
FS | 目前的分隔字符,默认是空格键 |
11.4.3 文本比对工具
diff通常用在同一个文件(或软件)的新旧版本差异上,以行为单位比对。不要用diff比较两个不相关的文件。
diff [-bBi] from-file to-file
from-file 文件名,作为原始比对文件的文件名
to-file 文件名,作为目标比对文件的文件名
from-file和to-file可以用-来替换,-此处代表标准输入
-b 忽略一行当中,仅有多个空白的差异,认为“a a”与“a a”相同
-B 忽略空白行的差异
-i 忽略大小写的不同
mkdir -p /tmp/testpw
cd /tmp/testpw/
cp /etc/passwd passwd.old
cat /etc/passwd | sed -e '4d' -e '6c no six line'>passwd.new
diff passwd.old passwd.new
输出:
4d3 左边第4行被删除了,基准是右边的第三行
< adm:x:3:4:adm:/var/adm:/sbin/nologin 列出了左边文件被删除的那一行内容
6c5 左边文件的第6行被替换成右边文件的第5行
< sync:x:5:0:sync:/sbin:/bin/sync 左边文件第6行
---
> no six line 右边文件第5行
diff /etc/rc0.d/ /etc/rc5.d/ 运行级别0和运行级别5的启动脚本文件对比
输出:
只在 /etc/rc0.d/ 存在:K90network
只在 /etc/rc5.d/ 存在:S10network
cmp [-l] file1 file2
-l 将所有不同点的字节处都列出来,默认仅输出第一个发现的不同点
cmp passwd.old passwd.new
输出:
passwd.old passwd.new 不同:第 106 字节,第 4 行
diff -Naur passwd.old passwd.new > passwd.patch 制作补丁文件
cat passwd.patch
输出:
--- passwd.old 2020-06-07 16:02:19.455870231 +0800
+++ passwd.new 2020-06-07 16:03:01.811869325 +0800
@@ -1,9 +1,8 @@
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
-adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
-sync:x:5:0:sync:/sbin:/bin/sync
+no six line
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
需要安装软件才能使用:
patch -pN < patch_file
patch -R -pN < patch_file
patch -p0 < passwd.patch 用刚刚制作出来的patch文件更新旧文件
patch -R -p0 <passwd.patch 恢复旧文件
11.4.4 文件打印设置:pr
打印的时候,打印标题和页码的设置。
pr /etc/man_db.conf
11.6 习题
grep '\*' /etc/* 2>/dev/null 找到/etc文件夹下的带*内容
grep '\*' $(find /etc -type f) 2>/dev/null 找到/etc包括子文件夹下的文件的带*内容
grep -l '\*' $(find /etc -type f) 2>/dev/null 找到符合的文件名就行,不用找内容
更多推荐
已为社区贡献2条内容
所有评论(0)