awk
执行过程
先执行BEGING,然后读取文件。
读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。
接着开始读入第二条记录,直到所有的记录都读完。
最后执行END操作。
命令格式
awk [-F field-separator] ‘commands’ input-file(s)
参数-F:是可选的,文件的每一行中,由域分隔符分开的每一项称为一个域,在不指定的情况下默认是空格。
参数commands:格式是’/pattern/ {action}‘,其中pattern是一个正则表达式,而action是当 awk 在该行中找到此模式时应当执行的动作。
参数input-file(s):input-file(s) 是待处理的文件。
参数/pattern/内容是空的,表示未指定任何模式,打印文件中的所有行。
awk ’// {print}’ /etc/hosts
搜索
awk -F: ‘/root/’ /etc/passwd # 包含root字符的行
awk -F: ’/^root/’ /etc/passwd # 以root字符串开头的行
打印指定域
awk -F: ’/^root/{print $7}’ /etc/passwd # 打印第七个域“/bin/bash”
Copy
使用“域”
2,…0为所有域。
行分隔符是分号,没有pattern参数处理所有行,打印第一个域的值。
awk -F ’:’ ‘{print $1}’ /etc/passwd
行分隔符是分号,没有pattern参数处理所有行,打印第一个和第七个域,中间添加tab分隔符。
awk -F ’:’ ‘{print 7}’ /etc/passwd
Copy
使用BEGIN和END
在开始和结尾打印一些东西,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。
awk -F ’:’ ‘BEGIN {print “|name\t|shell|”} {print 7} END {print “Over”}’ /etc/passwd
在BEGIN部分初始化一些东西
awk ‘BEGIN{for (i in ENVIRON) {print i”=“ENVIRON[i];}}’
Copy
使用内置变量
1表示当前行的第一个域,$2表示当前行的第二个域…
FILENAME awk程序浏览的文件名。
NR,已读的记录数,可以得到当前的行数。
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 系统环境变量的字典数组
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行 -F选项
NF 浏览记录的域的个数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
awk ‘/root/{printf(“NR:%s \t %s\n”,NR,$0)}’ /etc/passwd # 查找root字符所在行
Copy
使用外部变量
#!/bin/bash
for country in cat country_list
do
echo $country
awk -F ’|’ ’/‘“country"'/&&/ipv4/ {print 4 ”/” 32-log(5)/log(2)}' delegated-apnic-latest > ip_list_country
done
Copy
使用-v参数传递外部变量,可以在3种类型的action中都可以获得到,但需要放在所有的action前面。
test=‘something’
awk -v test=“$test” ‘BEGIN{print test}’
awk -v test=“$test” ‘{print test}‘
不使用-v参数,变量名=变量值放在所有的action后面。
awk ‘{print test}’ test=“$tt”
Copy
格式化输出
使用printf替代print获得更好的输出。
注意:字符串必须用双引号引用,参数用逗号分隔。
awk -F ’:’ ‘{printf(“FILENAME:%10s,NR:%s,NF:%s,Content:%s\n”,FILENAME,NR,NF,$0)}’ /etc/passwd
Copy
其他技巧
取三行数据组成一行。
awk ‘ORS=NR%3?” ”:“\n”{print}’ b.txt >c.txt
Copy
参考资料: