文件处理工具

讲述了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
...
上一篇:ACM: FZU 2102 Solve equation - 手速题


下一篇:SHELL编程之文本处理工具SED