awk
awk的工作模式是扫描文件中的每一行, 并且对符合条件的行进行处理, 处理的时候可以针对整行, 也可以针对行里的每个域。
所以awk两个最重要的参数就是:模式和动作, 根据模式找出符合条件的行, 然后执行指定的动作。
不指定模式的话默认就对于每一行都执行动作, 不指定动作的话默认就是把符合条件的行打印在屏幕上。
awk的语法
awk的语法如下
awk [options] 'pattern {action}' filename
或者
awk [options] -f script filename
第二种形式就是把'pattern {action}'
写在了文件里。
options
是可选的, 最常用的有两个:
-
-F seperator
,用来指定域的分隔符, 默认的分隔符是空格, 也就是每一个单词是一个域。可以指定多个域分隔符,此时应该把多个与分隔符放置在方括号中, 比如awk -F '[:-]' '{print $1,$3}' filename
, 使用:
或者-
作为域分隔符, 并且打印出第一个和第三个域 -
-v var=value
,用来指定一个用户自定义的变量, 可以稍后再pattern或者action中使用。
awk可以跟上多个pattern和action, 所以更一般的形式如下:
awk [options] 'pattern1 {action1} pattern2 {action2}...patternN {action}' filename
其中awk有内置的两个action, 叫做BEGIN
和END
,BEGIN在awk开始遍历file的时候执行,一般可以用来打印开始log或者定义在解析中用到的变量。 END在awk遍历文件结束的时候执行,一般用来打印结束的log.
所以awk的更一般的形势是:
awk [options] 'BEGIN {action} patternN {actionN} END {action}' filename
务必要记住, 在awk的单引号中, 所有的action都是在花括号中, 在花括号外面的都是pattern,BEGIN和END可以看做是两个特殊的pattern
花括号内可以有多个操作, 每个操作之间使用分号;分割, awk的操作支持使用所有的shell命令
awk的模式
awk的模式可以通过以下方式指定:
- 正则表达式,正则表达式一般都放在
/regular/
中间 - 关系表达式, 比如字符串或者数值大小的比较什么的
-
域 ~ 正则表达式
,域 !~ 正则表达式
, 域或者变量符合或者不符合某个正则表达式,~
和!~
分别表示域或者变量符合某个正则表达式或者不符合某个正则表达式 - 使用正则表达式指定的范围, 比如
/pattern1/,/pattern2/
awk内置的环境变量, 只介绍最常用的
- $n 第n个域,默认是以空格分割的
- $0 当前完整的记录,awk把每一个处理过的行都称为一个记录
- FILENAME 当前正在处理的文件的名称
- NR number of record, 当前已经处理过的记录的个数
- NF number of field, 当前正在处理的记录包含的域的个数
- FS field seperator域分隔符, 默认为空格
- RS record seperator记录分隔符, 默认为换行符
awk支持的运算符
awk支持编程语言中几乎所有的运算符,+ - * / ++ -- > < <= >= != && || ! += -= *= /= ?:
包括但不局限于加减乘除, 自加自减, 逻辑与或非, 三目运算符等。
还有两个非常值得注意的运算符:
-
~ !~
匹配正则表达式和不匹配正则表达式 -
in
某个变量或者域是否属于数组的成员
下面来看一个匹配和不匹配正则表达式操作符的例子
awk '$1 ~/^root/' filename
,打印出来第一个域以root开头的所有记录
下面看一些例子
-
awk '$1 + $3 >100' filename
打印所有第一个域和第三个域的和大于100的记录 -
awk '/root/,/chico/' filename
打印第一个包含root的行和第一个包含chico的行中间的所有行 -
awk '/^(no|so)/' filename
打印所有以no或者so开头的行 -
awk '/^(no|so)/ {print $2}' filename
打印所有以no或者so开头的行的第二个域 -
awk '$1 ~ /[0-9][0-9]$/ {print $1}'filename
打印以两个数字结尾的行的第一个域 -
awk '$1 >10 && $2 <30 {print $0}' filename
打印第一个域大于10并且第二个域小于30的所有行 -
awk '/^chicodong/{print $2}' filename
打印以chicodong开头的行的第二个域
在看一点复杂的, 在awk中使用变量。
比如awk '$1 ~ /^test/ {count=$2+$3;print count}' filename
,count就是一个变量,这个count=$1+$2
是赋值操作, 必须要放在action中。上面这个例子的含义是找出所有以test开头的行, 并且打印出来第二个域和第三个域的和。
更改域的值
看下面一个例子
awk '{$2=$1+10; print $2}' filename
, 就是把第二个域的值更改为第一个域的值加10.
再看一个例子
awk '$1=="root"{$1="chico";print}' filename
,如果第一个域是root,那么就把第一个域改成chico,并且打印出来。
awk内置的函数, 最常用的是printf, 用来格式化输出特别方便
echo "65"|awk '{print "%c\n", $0}'
, 可以打印出65对应的ASCII字符串。
网友评论