Awk
Awk是一种用于处理数据和生成报告的UNIX编程语言。
Awk已逐行方式扫描文件(或输入), 从第一行到最后一行,以查找匹配某个特定模式 的文本行,并对这些文本行执行(括在花括号)中的特定动作。
如果只给出模式而未给出动作,则打印所有匹配行; 如果只给出动作而未指定模式,会对所有输入行执行指定动作。
规则
一个规则包含一个模式,后跟一个操作。操作由花括号括起来以与模式分开。通常,换行符用来分开多个规则。
pattern { action }
pattern { action }
...
特别地,, { ? : || && do else
这些符号和关键字后的换行符被忽略,其它时候都被当作一个规则的结束。
多个规则也可以写在同一行,用 ;
分隔。
pattern1 { action1 } ; pattern2 { action2 }
模式
如果某个表达式中没有出现 if
,但实际却暗含 if
这个意思,那么,这个表达式就是“模式”。
模式不能被包括在 { }
中,模式包括:
-
正则表达式
/regular expression/
-
表达式
当表达式的值为非零或非空时匹配;否则不匹配
-
范围
pat1, pat2
一对用逗号分开的两个模式,用来指定一个连续范围的记录
-
BEGIN / END
-
BEGINFILE / ENDFILE
-
空
匹配每一条记录。
操作
操作由括在 { }
内的一条或多条语句组成,同一行内的多条语句之间用分号 ;
隔开,独占一行的语句则以换行符分隔。
缺省字段分隔符
缺省的字段分隔符是 FS = " "
,但 awk 对其特殊处理,将它扩展为空白序列,即包括空格,制表符和换行符。
如果仅仅按照字面意思,那么 " "
会将连续的两个空格分成两个独立的字段。
也可以用正则表达式作为字段分隔符,比如 FS = " "
与 FS = "[ \t\n]+"
大体相当,不过也有一些不同。前者时,awk 会剥落记录前导和后缀的空白字符,然后再分出字段;后者会将记录的前导空白字符作为第一个字段,后缀的空白字符作最后一个字段。
$ echo ' a b c d' | awk '{ print $2 }'
b
$ echo ' a b c d' | awk 'BEGIN { FS = "[ \t\n]+" } { print $2 }'
a
使用多个字段分隔符
如果有多个字符被用于字段分隔符FS
,则FS
对应是一个正则表达式,并且被包含在括号里:
$ awk -F '[ :\t]' '{print $1, $1}' file
改变字段值
一个字段值被改变,该记录也将马上重新计算以反映这个改变。也就是说,$0
包含的是字段值改变过的新记录。
$ awk '{ $2 = $2 - 10; print $0 }' inventory-shipped
Jan 3 25 15 115
Feb 5 32 24 226
Mar 5 24 34 228
...
使用超出范围的字段索引
仅仅索引一个超出范围的字段不会改变记录值,它只会返回一个空字符串。
单如果对一个超出范围的字段赋值,那么将会创建这个字段,NF
更新为这个最大索引值,$0
也将重建。如果这个时候打印 $0
,则会输出这个新字段,并且在该字段和原来的旧字段之间填入适当数量的 OFS
符号。
$ echo a b c d | awk '{ OFS = ":"; $2 = ""; $6 = "new"
> print $0; print NF }'
a::c:d::new
6
手动重建记录值
改变了字段值,$0
会自动重建;重新赋值 $0
,字段也会重新划分。可是仅仅通过改变 OFS
(即使在 BEGIN
里)并不会改变 $0
的值。要记住,$0
此时是一个由输入读取的完整的记录,包括前导和后置空格等,而 OFS
是用来输出字段的。
$ echo a b c d | awk 'BEGIN{ OFS = ":" } { print $0 }'
a b c d
可以通过使用看似无用的 $1 = $1
语句来重建 $0
:
$ echo a b c d | awk 'BEGIN{ OFS = ":" } { $1 = $1; print $0 }'
a:b:c:d
所谓重建 $0
是指,将 $1
直到 $NF
连接起来,中间用 OFS
分隔。下面的例子清晰地标明了 $0
一开始和重建后的不同:
$ echo " a b c d" | awk '{ print $0; $2 = $2; print $0 }'
a b c d
a b c d
空字符为分隔符
在 Gawk 里,如果设置 FS = ""
,便可将每个字符分割成一个字段。
传统的 awk 此时会将整个记录当成一个字段。
如果将 RS
设置为 ""
,这意味这将一行或者连续多行空行当作记录分隔符,没有其它更多所指。
OFS 和 ORS
ORS 控制记录的输出;OFS 控制字段的输出。
$ awk 'BEGIN { OFS = ";"; ORS = "\n\n" }
> { print $1, $1 }' mail-list
Amelia:555-5553
Anthony:555-3412
Becky:555-7685
...
删除 docker images
$ docker rmi `docker images | head | awk '$1~/echo-passthrough/{print $3}'`