讲述了linux上的两个文件处理工具:
- sed
- awk
sed
sed是一个管道命令,可以分析标准输入;还可以将数据进行替换、删除、新增、选取特定行等功能。
参数说明:
- -n:使用安静模式,只显示经过sed处理的那一行
- -e:直接在命令行模式上进行sed的操作编辑
- -i:直接修改读取的文件内容,而不是屏幕输出
- -E:扩展正则表达式
动作说明:
- a:新增,在下一行增加字符
- i:在上一行增加字符
- c:替换,替换n1,n2之间的行,n1,n2指范围
- d:删除
- p:打印
- s:替换某些字符,如: 1,20s/old/new/g
# 将/etc/passwd的内容列出并且打印行号,同时将2~5行删除
nl /etc/passwd | sed "2,5d"
输出
1 root:x:0:0:root:/root:/bin/bash
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
10 uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
11 operator:x:11:0:operator:/root:/sbin/nologin
12 games:x:12:100:games:/usr/games:/sbin/nologin
...
# 在第二行后加上“hello world”字符
nl /etc/passwd | sed "2a hello world"
输出
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
hello world
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
...
# 列出文件的3~5行
# 以前是根据head和tail来完成的
# head -n 5 /etc/passwd | tail -n 3
# 用sed的方法为
nl /etc/passwd | sed -n "3,5p"
输出
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
# 把He换成She并且把boy换成girl
echo "He is a boy" | sed -e "s/He/She/g" -e "s/boy/girl/g"
输出
She is a girl
# 有个t.log,包含一些如下数据的log,我只需要订单的order和product_id
# [INFO][root:467][2021-05-13 12:28:52,591]: Create order(609cab04133faa01d39669d9) successfully! uid(889900), product_id(com.hl.lz.yk), cash(3000)
# 先用egrep提取出需要的行,再用sed获取需要的order和product_id;处理分析大文件log的时候很有用。
egrep 'Create order\((\w+)\) successfully' t.log | sed -E 's/.*order\((\w+)\).*product_id\(([^)]*)\).*/\1 \2/g' > result.log
输出
# cat result.log
609cab04133faa01d39669d9 com.hl.lz.yk
上面的操作对于处理大文件的log还是很有用的。
# 用grep搜索当前目录下的某个字符串,并把字符串替换成另一个字符串,把“hello”替换成“world”
grep -rl 'hello' . --binary-files=without-match | xargs sed -i 's/hello/world/g'
# 或者
sed -i 's/hello/world/g' `grep -rl 'hello' . --binary-files=without-match`
# 如果当前目录下没有其他目录,只有文件,可以直接用sed
sed -i 's/hello/world/g' ./*
注意:grep 一定要加上-l, 表示只显示文件名。如果不加这个参数,sed执行不了
--binary-files=without-match 表示不找二进制文件,只查找文本文件
awk
awk是一个非常好用的数据处理工具,相较于sed常常用于一整个行的处理,awk则倾向于一行当中分成数个字段来处理。
awk常用模式:
awk '条件类型1{操作1} 条件类型2{操作2} ...' filename
awk主要用于处理每一行的字段内的数据,默认的字段分隔符为"空格键"或"[Tab]键"
注意:awk后续的所有操作是以单引号【'】括住的。
awk内置变量
变量名称 | 代表意义 |
---|---|
NF | 每一行($0)拥有的字段总数 |
NR | 目录awk处理的是第几行数据 |
FS | 分隔字符,默认是空格键 |
last -n 5
root pts/1 192.168.12.102 Fri May 21 23:07 - 23:07 (00:00)
root pts/1 192.168.12.102 Fri May 21 23:07 - 23:07 (00:00)
dmtsai pts/1 192.168.12.100 Fri May 21 23:07 - 23:07 (00:00)
dmtsai pts/1 192.168.12.100 Fri May 21 23:07 - 23:07 (00:00)
root pts/1 192.168.12.102 Fri May 21 20:12 - 20:12 (00:00)
# 获取登陆者的账号和登陆者的ip,中间以[Tab]隔开
last -n 5 | awk '{print $1 "\t" $3}'
root 192.168.12.102
root 192.168.12.102
dmtsai 192.168.12.100
dmtsai 192.168.12.100
root 192.168.12.102
$1 $2 $3 ...是每个字段的变量名称
# 列出目前正在处理的行数(NR变量),列出该行有多少个字段(NF)
last -n 5 | awk '{print $1 "\t lines: " NR "\t columns " NF}'
root lines: 1 columns 10
root lines: 2 columns 10
dmtsai lines: 3 columns 10
dmtsai lines: 4 columns 10
root lines: 5 columns 10
# 以冒号作为分隔符,并找出第三列小于10的数据
cat /etc/passwd | awk '{FS=":"} $3 < 10 {print $1 "\t" $3}'
root:x:0:0:root:/root:/bin/bash
bin 1
daemon 2
adm 3
...
# 此时第一行还是以空格键默认分隔,我们可以预先设置awk的变量,利用BEGIN这个关键词
cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t" $3}'
root 0
bin 1
daemon 2
adm 3
...