问题描述
如何使用 awk 处理分析文本数据。
问题分析
awk 是处理文本文件的一个应用程序,它依次处理文件的每一行,并读取里面的每一个字段。对于日志、CSV 那样的每行格式相同的文本文件,awk 处理十分方便
解决方案
1.awk 基础用法
# 格式
$ awk options 'selection _criteria {action }' input-file > output-file
# 示例
$ awk '{print $0}' test.txt > result.txt
示例中,test.txt 是 awk 所要处理的文本文件,result.txt 是结果输出的文件。'{}' 中的 print 0 代表当前行,因此上面命令的执行结果,就是把每一行原样打印出来。
awk 将每一行按照分隔符分成若干字段,依次用 2、$3 等代表第一个字段、第二个字段、第三个字段等。
使用/etc/passwd 文件进行测试:
这个文件的字段分隔符是冒号(:),所以要用-F参数指定分隔符为冒号。然后,才能提取到它的第一个字段跟第七个字段。
──(rootkali)-[~]
└─# awk -F ':' '{print $1,"-",$7}' /etc/passwd
root - /usr/bin/zsh
daemon - /usr/sbin/nologin
bin - /usr/sbin/nologin
sys - /usr/sbin/nologin
sync - /bin/sync
games - /usr/sbin/nologin
……
2.使用变量
除了 1)表示某个字段,awk还可以使用其他变量。
如变量 NF 表示当前行有多少个字段,因此$NF就代表最后一个字段,示例:
┌──(root)-[~]
└─# awk -F ':' '{print $NF}' /etc/passwd
/usr/bin/zsh
/usr/sbin/nologin
/usr/sbin/nologin
/usr/sbin/nologin
/bin/sync
$(NF-1) 则表示倒数第二个字段,示例:
┌──(root)-[~]
└─# awk -F ':' '{print $1,$(NF-1)}' /etc/passwd
root /root
daemon /usr/sbin
bin /bin
sys /dev
sync /bin
变量 NR 表示当前处理的是第几行,示例:
┌──(root)-[~]
└─# awk -F ':' '{print NR"-" $1}' /etc/passwd
1-root
2-daemon
3-bin
4-sys
5-sync
其他变量:
- FILENAME:当前文件名
- FS:字段分隔符,默认是空格和制表符。
- RS:行分隔符,用于分割每一行,默认是换行符。
- OFS:输出字段的分隔符,用于打印时分隔字段,默认为空格。
- ORS:输出记录的分隔符,用于打印时分隔记录,默认为换行符。
- OFMT:数字输出的格式,默认为%.6g。
3.函数使用
awk 提供了一些内置函数来处理数据,如函数 toupper()用于将字符转为大写,示例:
┌──(root)-[~]
└─# awk -F ':' '{print toupper($1)}' /etc/passwd
ROOT
DAEMON
BIN
SYS
上面示例将小写转换成大写。
函数 length 返回字符串长度,示例:
┌──(root)-[~]
└─# awk -F ':' '{print $1,"length is",length($1)}' /etc/passwd
root length is 4
daemon length is 6
bin length is 3
sys length is 3
其他函数:
- tolower():字符转为小写。
- substr():返回子字符串。
- sin():正弦。
- cos():余弦。
- sqrt():平方根。
- rand():随机数。
4.条件使用
awk 允许指定输出条件,只输出符合条件的行,示例:
┌──(root)-[~]
└─# awk -F ':' '/root/ {print $1}' /etc/passwd
root
上面示例,/root/是一个正则表达式,只输出包含usr的行。
下面示例输出奇数行,如下:
┌──(root)-[~]
└─# awk -F ':' 'NR % 2 == 1 {print NR,"-",$1}' /etc/passwd
1 - root
3 - bin
5 - sync
7 - man
下面示例输出第一个字段为特定字符串的行,如下:
┌──(root)-[~]
└─# awk -F ':' '$1 == "root" {print NR,"-",$1}' /etc/passwd
1 - root
┌──(root)-[~]
└─# awk -F ':' '$1 == "root" || $1 == "bin" {print NR,"-",$1}' /etc/passwd
1 - root
3 - bin
5.if语句使用
awk 可以使用 if 语句,来编写条件,示例:
┌──(root)-[~]
└─# awk -F ':' '{if($1 > "q") print $1;else print "----"}' /etc/passwd
root
----
----
sys
sync
参考文档:
[1] https://linux.die.net/man/1/awk
如果您有其他问题,欢迎您联系火山引擎技术支持服务