zhaoyu@home:~$

linux命令-awk

awk是一种文本处理工具。语法如下: ```shell script awk [选项] ‘script’ file … awk [选项] -f scriptfile file …

### 选项
* -F 文件分隔符,一个字符串或者正则表达式。如`-F:`,分隔符为冒号。
* -f scrptfile,从文件中读取awk脚本。
* -W help或者--help。
* -v var=val 设置自定义变量值。

### 内建变量
* $n 当前记录的第n列,有FS分割,从1开始。
* $0 处理前的完整的记录。
* $NF 当前记录的最后一行。
* FS 输入字段分隔符(默认是任何空格)。
* OFS 输出字段分隔符(输出换行符),输出时用指定的符号代替换行符。
* RS 输入记录分隔符(默认是换行符\n)
* ORS 输出记录分隔符(默认是换行符\n)。
* NR 行号。从1开始。
* NF 表示每一行中有几列。
* FIELDWIDTHS 字段宽度列表。

```shell script
echo "111 222|333 444|555 666"|awk 'BEGIN{RS="|"}{print $0}' # 将默认的换行符改为| 

ORS 可以理解为RS的反操作,假如有如下文件log.txt

this is 1 line.
2 line.
three line is aaaa.

默认的ORS还是换行符,将ORS修改为| ```shell script awk ‘BEGIN{ORS=”|”}{print $0}’ log.txt

输出如下:

this is 1 line.|2 line.|three line is aaaa.|

FS和OFS原理类似。

按宽度指定分隔符
```shell script
echo 20100117054932 | awk 'BEGIN{FIELDWIDTHS="4 2 2 2 2 2"}{print $1"-"$2"-"$3,$4":"$5":"$6}'

例子

基本使用

```shell script awk ‘{print $1,$4}’ log.txt # 输出文本中的第一列和第四列。 awk ‘{printf “%-8s %-10s\n”,$1,$4}’ log.txt # 格式化输出 awk -F ‘[ ,]’ ‘{print $1,$2,$5}’ log.txt # 使用 或者,作为分割符。 awk -va=1 -vb=s ‘{print $1,$1+a,$1b}’ log.txt # 设置变量a,b


#### 过滤
```shell script
awk '$1>2' log.txt  #过滤第一列大于2的行。
awk '$1==2 {print $1,$3}' log.txt    #第一列等于2的行
awk '$1>2 && $2=="Are" {print $1,$2,$3}' log.txt    #第一列大于2且第二列等于‘Are’

正则表达式

```shell script awk ‘$2 ~ /th/ {print $0}’ log.txt # 输出第二列包含‘th’的行。

`~` 表示表达式开始。`//` 中是表达式
```shell script
awk 'BEGIN{IGNORECASE=1} /this/' log.txt #忽略大小写
awk '$2 !~ /th/ {print $0}' log.txt #表达式取反,取不包含th的行。
awk '/^root/{print $0}' /etc/passwd #root开头的行

脚本

awk脚本关键字有BEGIN和END。

  • BEGIN{处理行之前执行的语句}
  • {处理每一行时需要执行的语句}
  • END{处理完所有行后要执行的语句}

脚本例子如下: ```shell script #!/bin/awk -f BEGIN{ FS=”:” thirdsum=0 printf “————begin————\n” } { thirdsum=thirdsum+$3 printf “%-24s %-6s %8d.\n”,$1,$2,$3 } END{ printf “———–end—————\n” printf “thirdsum=%-8s.\n”,thirdsum }

运行脚本如下:
```shell script
awk -f test.awk /etc/passwd

也可以直接在命令。

for循环

```shell script netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’

其中NF是每行的列数,那么$NF就是取最后一列。++S[]表示按关键字统计个数。如,hello world hello统计结果为
`S["hello"]=2,S["world"]=1`。`for(a in S) print a, S[a]`就好理解了,循环打印S。上面命令为统计tcp网络请求每种状态的数量,结果如下:

CLOSE_WAIT 41 ESTABLISHED 464 FIN_WAIT2 1 TIME_WAIT 16 ``` TCP连接双方都可以调用close()方法关闭连接,发起关闭的一方为主动方,另一方为被动方。 常用的三个状态是:ESTABLISHED 表示正在通信,TIME_WAIT 表示主动关闭,CLOSE_WAIT 表示被动关闭。 CLOSE_WAIT,是被动连接方的一个中间状态。表示协议层在等待上层的应用程序,主动调用close操作后才主动关闭这条连接 。

CLOSE_WAIT很多,表示说要么是你的应用程序写的有问题,没有合适的关闭socket;要么是说,你的服务器CPU处理不过来(CPU太忙)或者你的应用程序 一直睡眠到其它地方(锁,或者文件I/O等等),你的应用程序获得不到合适的调度时间,造成你的程序没法真正的执行close操作。