awk教程
AWK是一种处理文本文件的语言,是一个强大的文本分析工具。
之所以叫AWK是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的 Family Name 的首字符。
一、awk的基本用法
# 格式
$ awk 动作 文件名
# 示例
$ awk '{print $0}' demo.txt
print是打印命令,$0表示当前行
[root@Server-n93yom ~]# echo 'this is a test' | awk '{print $0}'
this is a test
上面使用管道命令,输出的就是 this is test
awk
会根据空格和制表符,将每一行分成若干字段,依次用$1
、$2
、$3
代表第一个字段、第二个字段、第三个字段等等。
变量NF
表示当前行有多少个字段,因此$NF
就代表最后一个字段。
[root@Server-n93yom ~]# echo 'this is a test' | awk '{print $4}'
test
[root@Server-n93yom tmp]# echo 'this is test' | awk '{print $NF}'
test
我们以/etc/passwd文件为例,用-F来指定分隔符为冒号,然后取第一个字段,则可以执行以下命令
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 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 operator:x:11:0:operator:/root:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin dbus:x:81:81:System message bus:/:/sbin/nologin polkitd:x:998:996:User for polkitd:/:/sbin/nologin tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin check:x:1000:1000:check:/home/check:/bin/bash cfyuser:x:10000:10000::/home/cfyuser:/bin/bash consul:x:10002:10002::/opt/cloudchef/consul:/sbin/nologin rabbitmq:x:10003:10003::/etc/rabbitmq:/sbin/nologin mysql:x:10009:10009::/home/mysql:/bin/bash prometheus:x:10004:10004::/home/prometheus:/sbin/nologin grafana:x:10005:10005::/home/grafana:/bin/bash logstash:x:10006:10006::/home/logstash:/bin/bash nginx:x:997:995:nginx user:/var/cache/nginx:/sbin/nologin tomcat:x:10008:10008::/opt/cloudchef/tomcat:/sbin/nologin test:x:10010:10010::/home/test:/bin/bash test1:x:10011:10011::/home/test1:/bin/bash
[root@Server-n93yom tmp]# awk -F ':' '{print $1}' passwd root bin daemon adm lp sync shutdown halt mail operator games ftp nobody systemd-bus-proxy systemd-network dbus polkitd tss postfix sshd check cfyuser consul rabbitmq mysql prometheus grafana logstash nginx tomcat test test1
二、变量
$(NF-1)
代表倒数第二个字段。
[root@Server-n93yom tmp]# awk -F ':' '{print $1,$(NF-1)}' passwd root /root bin /bin daemon /sbin adm /var/adm lp /var/spool/lpd sync /sbin shutdown /sbin halt /sbin mail /var/spool/mail operator /root games /usr/games ftp /var/ftp nobody / systemd-bus-proxy / systemd-network / dbus / polkitd / tss /dev/null postfix /var/spool/postfix sshd /var/empty/sshd check /home/check cfyuser /home/cfyuser consul /opt/cloudchef/consul rabbitmq /etc/rabbitmq mysql /home/mysql prometheus /home/prometheus grafana /home/grafana logstash /home/logstash nginx /var/cache/nginx tomcat /opt/cloudchef/tomcat test /home/test test1 /home/test1
上面代码中,print
命令里面的逗号,表示输出的时候,两个部分之间使用空格分隔。
NR表示当前处理的第几行
[root@Server-n93yom tmp]# awk -F ':' '{print NR ")" $(NF-1)}' passwd 1)/root 2)/bin 3)/sbin 4)/var/adm 5)/var/spool/lpd 6)/sbin 7)/sbin 8)/sbin 9)/var/spool/mail 10)/root 11)/usr/games 12)/var/ftp
其他的一些内置变量
变量 | 描述 |
---|---|
$n | 当前记录的第n个字段,字段间由FS分隔 |
$0 | 完整的输入记录 |
ARGC | 命令行参数的数目 |
ARGIND | 命令行中当前文件的位置(从0开始算) |
ARGV | 包含命令行参数的数组 |
CONVFMT | 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组 |
ERRNO | 最后一个系统错误的描述 |
FIELDWIDTHS | 字段宽度列表(用空格键分隔) |
FILENAME | 当前文件名 |
FNR | 各文件分别计数的行号 |
FS | 字段分隔符(默认是任何空格) |
IGNORECASE | 如果为真,则进行忽略大小写的匹配 |
NF | 一条记录的字段的数目 |
NR | 已经读出的记录数,就是行号,从1开始 |
OFMT | 数字的输出格式(默认值是%.6g) |
OFS | 输出记录分隔符(输出换行符),输出时用指定的符号代替换行符 |
ORS | 输出记录分隔符(默认值是一个换行符) |
RLENGTH | 由match函数所匹配的字符串的长度 |
RS | 记录分隔符(默认是一个换行符) |
RSTART | 由match函数所匹配的字符串的第一个位置 |
SUBSEP | 数组下标分隔符(默认值是/034) |
三、函数
toupper表示把字段变为大写
[root@Server-n93yom tmp]# awk -F ':' '{print NR ")" toupper($1)}' passwd 1)ROOT 2)BIN 3)DAEMON 4)ADM 5)LP 6)SYNC 7)SHUTDOWN 8)HALT 9)MAIL 10)OPERATOR 11)GAMES 12)FTP 13)NOBODY 14)SYSTEMD-BUS-PROXY 15)SYSTEMD-NETWORK 16)DBUS
其他的内置函数如下
tolower():字符转为小写。
length():返回字符串长度。
substr():返回子字符串。
sin():正弦。
cos():余弦。
sqrt():平方根。
rand():随机数。
四、条件
awk
允许指定输出条件,只输出符合条件的行。
awk '条件 动作' 文件名
下面是输出包含test1的行
[root@Server-n93yom tmp]# awk -F ':' '/test1/ {print $(NF-1)}' passwd /home/test1 [root@Server-n93yom tmp]#
输出行数是偶数的行
[root@Server-n93yom tmp]# awk -F ':' 'NR%2 == 0 {print NR ")" $(NF-1)}' passwd 2)/bin 4)/var/adm 6)/sbin 8)/sbin 10)/root 12)/var/ftp 14)/ 16)/ 18)/dev/null 20)/var/empty/sshd 22)/home/cfyuser 24)/etc/rabbitmq 26)/home/prometheus 28)/home/logstash 30)/opt/cloudchef/tomcat 32)/home/test1
输出前4行
[root@Server-n93yom tmp]# awk -F ':' 'NR<=4 {print NR ")" $(NF-1)}' passwd 1)/root 2)/bin 3)/sbin 4)/var/adm
输出第一个字段为nginx或tomcat的行
[root@Server-n93yom tmp]# awk -F ':' '$1=="nginx" || $1=="tomcat" {print $1}' passwd nginx tomcat [root@Server-n93yom tmp]# awk -F ':' '$1=="nginx" || $1=="tomcat" {print NR ")" $1}' passwd 29)nginx 30)tomcat
五、if语句
输出第一个字段的第一个字符大于t的行
[root@Server-n93yom tmp]# awk -F ':' ' {if($1>"t") print $1}' passwd
tss
tomcat
test
test1
还可以使用else把未匹配到的用----输出
[root@Server-n93yom tmp]# awk -F ':' ' {if($1>"t") print $1; else print "------" }' passwd ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ tss ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ ------ tomcat test test1
LeetCode题型
给定一个文件 file.txt,转置它的内容。
你可以假设每行列数相同,并且每个字段由 ' ' 分隔.
示例:
假设 file.txt 文件内容如下:
name age alice 21 ryan 30
应当输出:
name alice ryan age 21 30
awk是一行一行地处理文本文件,运行流程是:
先运行BEGIN后的{Action},相当于表头
再运行{Action}中的文件处理主体命令
最后运行END后的{Action}中的命令
有几个经常用到的awk常量:NF是当前行的field字段数;NR是正在处理的当前行数。
注意到是转置,假如原始文本有m行n列(字段),那么转置后的文本应该有n行m列,即原始文本的每个字段都对应新文本的一行。我们可以用数组res来储存新文本,将新文本的每一行存为数组res的一个元素。
在END之前我们遍历file.txt的每一行,并做一个判断:在第一行时,每碰到一个字段就将其按顺序放在res数组中;从第二行开始起,每碰到一个字段就将其追加到对应元素的末尾(中间添加一个空格)。
文本处理完了,最后需要输出。在END后遍历数组,输出每一行。注意printf不会自动换行,而print会自动换行。
awk '{ for (i=1;i<=NF;i++){ if (NR==1){ res[i]=$i } else{ res[i]=res[i]" "$i } } }END{ for(j=1;j<=NF;j++){ print res[j] } }' file.txt
参考:http://www.ruanyifeng.com/blog/2018/11/awk.html
http://www.zsythink.net/archives/tag/awk/
作者:guanbin —— 纵码万里千山
出处:https://www.cnblogs.com/guanbin-529/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。