针对Linux系统文本过滤,一般我们都会用到三个命令进行过滤。这里我简单描述下三种过滤的使用场景及方法。
grep:使用方法简单,简单的文本过滤。
sed:擅长数据修改,awk擅长数据切片,数据格式化,功能最复杂。
awk:擅长数据切片,数据格式化,功能最复杂。
首先说明,如果grep过滤没有颜色,我们需要执行一个命令即可。
编辑配置文件~/.bash_profile 增加alias grep='grep --color'一行。
然后source ~/.bash_profile 生效后即可有颜色。
正则表达式含义说明
表达式 |
说明 |
示例 |
[] |
括号里的字符任选其一 |
[abc]\[0-9]\[a-z] |
[^] |
不匹配括号里的任意字符(括号里面的^号为"非",不是开头) |
[^abc]表示不是a,不是b,不是c |
^[] |
以括号里的任意单个字符开头(这里的^是开头的意思) |
^[abc]:以a或b或c开头 |
^[^] |
不以括号里的任意单个字符开头 |
|
^ |
行的开头 |
^root |
$ |
行的结尾 |
bash$ |
^$ |
空行 |
grep使用说明
dengpeng@dengpengdeMacBook-Air ~ % cat 1.sh
aa
bb
cc
dd
ff
dengpeng@dengpengdeMacBook-Air ~ % cat 1.sh | grep aa
aa
#打印出含有aa的行
dengpeng@dengpengdeMacBook-Air ~ % cat 1.sh | grep -E 'aa|bb'
aa
bb
#打印出含有aa或bb的行,需要开启扩展模式,增加-E参数,
dengpeng@dengpengdeMacBook-Air ~ % cat 1.sh | grep -v aa
bb
aa
dd
ff
#添加-v为取反的意思,打印不含aa的行
dengpeng@dengpengdeMacBook-Air ~ % cat 1.sh | grep '^a'
aa
#打印出来以a为首的行
dengpeng@dengpengdeMacBook-Air ~ % cat 1.sh | grep 'a$'
aa
#打印出来以a结尾的行
sed使用案例演示
sed参数
-e 进行多项编辑,即对输入行应用多条sed命令时使用
-n 取消默认的输出
-r 使用扩展正则表达式
-i inplace,原地编辑(修改源文件)
sed操作
d 删除行
p 打印行
a 后面加行
i 前面加行
s 替换修改
sed #删除行操作
head -5 /etc/passwd |cat -n |sed 2d #指定删除第2行
head -5 /etc/passwd |cat -n |sed "$a"d #变量引用需要双引号
head -5 /etc/passwd |cat -n |sed 2,3d #删除第2行到第3行,中间的逗号表示范围
head -5 /etc/passwd |cat -n |sed '1d;5d'#删除第1行和第5行,中间为分号,表示单独的操作
head -5 /etc/passwd |cat -n |sed -e '2d;4d' -e '1d' #删除第1,2,4行, -e参数是把不同的多种操作可以衔接起来
head -n 5 /etc/passwd |cat -n |sed '/oo/d' #删除匹配oo的行
sed -i '/#/d;/;/d;/^$/d;/^\t$/d' /etc/samba/smb.conf #`sed -i`删除/etc/samba/smb.conf里所有的注释和空行
sed #打印行操作
head -5 /etc/passwd |cat -n | sed 1p
1 root:x:0:0:root:/root:/bin/bash # 会在原来5行的基础上再打印第1行
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
head -5 /etc/passwd |cat -n | sed -n 1p # 正确做法加一个-n参数
1 root:x:0:0:root:/root:/bin/bash
sed #增加行操作
# cat 1.txt #准备一个文件里面输入如下文本
11111
22222
44444
55555
# sed -i '2a33333' 1.txt #在第2行后加上33333这一行,第一行前面插入用li
# cat 1.txt
11111
22222
33333
44444
55555
# sed -i '/^4/accccc' 1.txt #使用正则匹配行,这里表示在4开头的行的后一行加上ccccc这一行
sed 修改跟替换操作
head -5 /etc/passwd |sed 's/:/===/' #替换每行里的第1个匹配字符
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
head -5 /etc/passwd |sed 's/:/===/g' #替换每行配置的所有字符
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
head -5 /etc/passwd |sed '2,4s/:/===/g' #替换2到4行所有匹配字符
head -5 /etc/passwd |sed '2s/:/===/g;4s/:/===/g' #替换2行和4行匹配字符
head -5 /etc/passwd |sed '2s/:/===/;2s/:/===/2' #替换第2行的第1个和第3个匹配字符,注意后面的数字是2,前面替换了1个,剩下的里面替换第2个也就是原来的第3个
sed 正则匹配
head -5 /etc/passwd |sed '/^daemon/s/:/===/g' #替换以daemon开头的那一行
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
awk使用说明
运算符 |
说明 |
== |
等于 和shell里不一样,shell里字符串比较是= ;数字比较是-eq |
!= |
不等于 shell里数字比较是-ne代表不等于 |
> |
大于 shell里数字比较是(-gt)代表大于 |
< |
小于 shell里数字比较是(-lt)代表小于 |
>= |
大于等于 shell里数字比较是(-ge)代表大于等于 |
<= |
小于等于 shell里数字比较是(-le)代表小于等于 |
&& |
逻辑与(和) [条件1 -a 条件2] |
|| |
逻辑或 [条件1 -o 条件2] |
+ |
加法 |
- |
减法 |
* |
乘法 |
/ |
除法 |
% |
求余数 |
常用变量 |
说明 |
$0 (常用) |
当前处理行的所有记录(所有列数之和,包括分隔符) |
$1 到 \$n (常用) |
文件中每行以间隔符号分割的不同字段($1代表第1列。。。。。。以此类推) |
NF (常用) |
当前记录的字段数(列数) |
$NF (常用) |
最后一列 |
NR (常用) |
行号 |
FS (常用) |
定义间隔符,等同于-F参数 |
使用awk截取,多个空格也只算一个分隔符(并且是默认的,不用-F指定分隔符),所以$2(第2列)就找到了额ip地址的那部分
head -3 /etc/passwd |awk -F: '{print $1}' #打印文件每行的第一列以:为分隔符
#awk可以将文本截取多段后自由拼接
head -3 /etc/passwd |awk -F":" '{print $1"用户的uid是"$3}'
root用户的uid是0
bin用户的uid是1
daemon用户的uid是2
awk -F: '{print $NF}' /etc/passwd #截取/etc/passwd文件的最后一列
awk -F: '{print $(NF-1)}' /etc/passwd #截取/etc/passwd文件的倒数第二列
awk 行匹配操作
awk -F":" '$1=="daemon" {print $3}' /etc/passwd #从/etc/passwd里查找出daemon用户的uid
awk 'NR==5 {print $0}' /etc/passwd #打印/etc/passwd第五行
awk -F: 'NR==5 || NR==6 {print $0}' /etc/passwd #打印第五行和第六行
awk 正则匹配
awk '$0~"root" {print $0}' /etc/passwd #打印所有root的行
awk -F: '$1=="root" {print $0}' /etc/passwd #查找/etc/passwd文件里用户名为root的行
awk -F: '$1!="root" {print $0}' /etc/passwd #查找/etc/passwd文件里用户名不为root的行
awk -F: '$1!~"oo" {print $0}' /etc/passwd #查找/etc/passwd文件里用户名里不包含oo这两个字符的行