-- TOC --
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
awk命令的功能可以写一本书,这里只是做点个人总结。
awk可以接收stdin的输入,也可以读文件:
$ echo sth | awk ...
$ awk ... <filename>
在命令行的世界中,不同工具之间的数据交换基本都是通过管道,左边命令的输出stdout是右边命令的输入stdin,获取命令输出的方式,
|
或者$(cmd)
赋值,awk的print输出也就是输出到stdout的意思。
用-F
指定field seperator,默认是空格。
$ uname -a | awk '{print $0}'
Linux K 5.14.14 #1 SMP Tue Oct 26 10:20:53 CST 2021 x86_64 x86_64 x86_64 GNU/Linux
$ uname -a | awk '{print $1}'
Linux
$ echo '123a567a789a' | awk -Fa '{print $2}'
567
$0
表示整行,field从$1
开始编号!可以借助此功能,对列进行重新排列:
$ echo 'a b c' | awk '{print $2" "$1" "$3}'
b a c
$ echo a b c | awk '{print $2,$1,$3}'
b a c
$ echo 'a b c' | awk "{print \$1 \$2 \$3}"
abc
""
括起来的部分是raw格式输出,在其中使用awk分割出来的field,要用\
转义。
单引号时,将单引号内所有内容原样传递给awk去解析;双引号时,如果不用
\
转义,bash就会将$1
展开。
下面是一个带条件提取field的case:
$ cat /proc/devices | grep mem
1 mem
$ awk '$2=="mem" {print $1}' /proc/devices
1
$ awk "\$2==\"${mem}\" {print \$1}" /proc/devices # ??
1
另一种写法如下,先用关键词匹配某一行,然后再输出field:
$ awk '/mem/{print $1}' /proc/devices
1
$ awk '/em/{print $1}' /proc/devices
1
提取最后一列的技巧:NF
和$NF
$ uname -a | awk '{print NF" "$NF}'
15 GNU/Linux
NF是awk的一个内置变量,值为列数,$NF自然就是最后一列了!
NR
也是内置变量,表示当前行数,从1开始!
显示当前分区剩余的空间:
$ df -k . | awk 'NR==2 {printf("%d%%, %d Bytes \n", $5, $4)}'
70%, 11886388 Bytes
print有的时候还不够,更复杂的控制输出的方式,还是printf。
$ echo '1 2 3' | awk '{printf("%d - %0.2f - %d\n",$1,$2,$3)}'
1 - 2.00 - 3
$ df -h | awk '{printf("%18s %-4s\n", $1,$5)}'
$ df -h | awk '{printf "%18s %-4s\n",$1,$5}' # 没有括号也OK!
Filesystem Use%
udev 0%
tmpfs 1%
/dev/sda5 69%
tmpfs 0%
tmpfs 1%
tmpfs 0%
/dev/loop0 100%
/dev/loop1 100%
/dev/loop2 100%
/dev/loop3 100%
/dev/loop4 100%
/dev/loop5 100%
/dev/loop6 100%
/dev/loop8 100%
/dev/loop9 100%
/dev/loop10 100%
/dev/loop11 100%
/dev/loop12 100%
/dev/loop7 100%
/dev/sda1 1%
tmpfs 1%
看到一种用法,用awk的printf输出一个字符串,然后用eval执行此字符串!举个例子:
$ cmd=$(echo 1 | awk '{printf("sleep %s", $1)}')
$ eval $cmd # 没有eval也OK
来自一个shell脚本文件:
if [ -f $NETCFG_FILE ] ; then
echo "$NETCFG_FILE exist"
argv=`awk -F ':' '{printf("dhcpoff=%s;ip=%s;mask=%s;gw=%s;dns1=%s;dns2=%s;",$1,$2,$3,$4,$5,$6)}' $NETCFG_FILE`
eval $argv
fi
$argv
实际上就是一行赋值命令,生成了一组shell变量,这条命令的组成来自awk和printf。
本文链接:https://cs.pynote.net/sf/linux/shell/202112017/
-- EOF --
-- MORE --