文本过滤工具:
grep--搜索文本合适
sed--编辑文本合适
awk--生成格式化的文本工具
awk:将文本分隔,自由的处理某个或某段符合条件的文本,支持数组,支持各种变量,是一种文本处理的语言;

用法:
awk [options] 'scripts' file1,file2...
awk [options] 'pattern {action}' file1,file2...

注:options 是awk支持的选项,scripts 是脚本,包含模式pattern动作action

awk对文本处理的时候先切片,每个片用$1,$2...依次引用,对整行用$0引用,使用指定的分隔符来分隔,默认是空白字符进行分隔;

例如:

手动创建一个文件,里面内容如下:

  1. vim a.txt  
  2.  
  3. welcome to linux magedu  
  4. how are you?  
  5. I'm fine, thank you!  

awk '{print $1}' a.txt

  1. [root@Fuyaxu ~]# awk '{print $1}' a.txt  
  2. welcome  
  3. how  
  4. I'm 


print:显示文本,后面显示多个字段时,用逗号隔开
选项:
-F:指定字段分隔符

-v:声明一个变量
例如:awk -F: '{print $1,$7}' /etc/passwd

  1. [root@Fuyaxu ~]# awk -F: '{print $1,$7}' /etc/passwd  
  2. root /bin/bash  
  3. bin /sbin/nologin  
  4. daemon /sbin/nologin  
  5. adm /sbin/nologin  
  6. lp /sbin/nologin  
  7. sync /bin/sync 

awk 的内置变量:
NF:显示当前行的字段的个数,$NF会显示最后一个字段,还可以对该变量做数学运算;
例如:awk '{print NF}' a.txt
awk '{print $NF}' a.txt

FS:字段分隔符,改变该变量的值也可以实现分隔符的变换
例如:awk -v FS=: '{print $1}' /etc/passwd

OFS:指定输出的段分隔符
例如:awk -v OFS=: '{print $1,$2}' /etc/passwd

printf:格式化的显示命令,要指定格式
格式:

printf  format ,statement1 ,statement2....
printf  格式,字段1,字段2...

要点:
1.其与print命令的最大不同是,printf需要指定format(格式)
2.format用于指定后面的每个item(字段)的输出格式
3.printf语句不会自动打印换行符,\n,自己指定换行

format格式的指示符都以%开头,后面跟一个字符
%c:         显示字符的ASCII码
%d,%i:十进制整数
%e,%E: 科学计数法显示数值;
%f:         显示浮点数
%g,%G:以科学计数法的格式或浮点数的格式显示数值
%s:        显示字符串
%u:        无符号整数
%%:      显示%自身

修饰符:
N(数字):显示宽度
-:左对齐,默认是右对齐
+:显示数值符号
例如:awk '{printf "%-10s%s\n", $1,$2}' a.txt
awk '{printf "%10s %s\n", $1,$2}' a.txt
注:格式之间不用使用符号

三、输出重定向
print items > output_file
print items >> output_file
print items | command

特殊文件描述符:
/dev/stdin:    标准输入
/dev/sdtout: 标准输出
/dev/stderr:  错误输出
/dev/fd/N:    某特定文件描述符,如/dev/stdin就相当于/dev/fd/0;

例如:awk -F: '{printf "%-15s %i\n",$1,$3 > "/dev/stderr"}' /etc/passwd

awk的操作符:
一、算术操作符

-x:    负值
+x:  转换为数值
x^y: 次方
x**y:   次方
x*y: 乘法
x/y:   除法
x+y: 加法
x-y:  减法
x%y:取余

二、字符串操作符
只有一个,而且不用写出来,用于实现字符串连接;
例如:awk 'BEGIN{print "a","b"}'       ##显示a,b字符,BEGIN的用法下面会说到

三、赋值操作符

=
+=
-=
*=
/=
%=
^=
**=

++
--
需要注意的是,如果某模式为=号,此时使用/=/可能会有语法错误,应以/[=]/替代;

四、布尔值

awk中,任何非0值或非空字符串都为真,反之就为假;

五、比较操作符

x < y
x <= y
x > y
x >= y
x == y
x != y
x ~ y
x !~ y
subscript in array     #数组中的子脚本
例如:awk -F: '$1 ~/^root/{print $3,$4,$NF}' /etc/passwd

#匹配第一个字段$1中以root开头的行,显示这些行的第3,4和最后一个字段

六、表达式间的逻辑关系符
&&:与
||:或

七、条件表达式
selector?if=true=exp:if=false=exp

  1. 例如:  
  2. A=3 
  3. B=4 
  4. $A>$B?echo $A:echo $B  
  5. 这相当于一个条件表达式,如果A>B 就显示A ,否则就显示B 

八、函数调用
function_name (parament1,parament2...) 

awk的模式:
awk 'program' input=file1 input=file2...
其中的program为:
pattern { action }
pattern { action }

………………

常见的模式类型:
1、regexp: 正则表达式,格式为/regular expression/
例如:awk -F: '/bash/{print $0}' /etc/passwd    #显示匹配bash的行
2、expression:表达式,其值非0或非空字符时满足条件,如:$1 ~ /foo/或 $1 == "magedu", 用运算符~(匹配)和!~(不匹配);
例如: awk -F: '$3>=500{print $1}' /etc/passwd   #显示第三个字段中大于500的行
3、ranges:指定的匹配范围,格式为pat1,pat2
和sed命令用法一样
4、BEGIN/END:特殊模式,仅在执行前运行一次或结束前运行一次;
例如:awk -F: 'BEGIN{print "Username     UID"}{printf "%-10s%s\n",$1,$3}' /etc/passwd     #在显示的所有行中行首添加标头

  1. [root@Fuyaxu ~]# awk -F: 'BEGIN{print "Username     UID"}{printf "%-10s%s\n",$1,$3}' /etc/passwd       
  2. Username     UID  
  3. root      0  
  4. bin       1  
  5. daemon    2  
  6. adm       3  
  7. lp        4  
  8. sync      5  
  9. shutdown  6 

awk -F: 'END{print "The end"}{printf "%-10s%s\n",$1,$3}' /etc/passwd    #显示一个结尾

  1. [root@Fuyaxu ~]# awk -F: 'END{print "The end"}{printf "%-10s%s\n",$1,$3}' /etc/passwd  
  2. root      0  
  3. bin       1  
  4. daemon    2  
  5. adm       3  
  6. ...........  
  7. hduser    502  
  8. mysql     503  
  9. apache    48  
  10. The end 

在BEGIN中赋值:
例如:awk 'BEGIN{FS=":"}{print $1,$3}' /etc/passwd    #给FS指定分隔符
5、Empty(空模式):匹配很多行;

常见的Action有:
1,Expressions                       #表达式
2,Control statements            #控制字段
3,Compound statements      #混合字段
4,Input statements               #输入字段
5,Output statements            #输出字段

/正则表达式/: 使用通配符的扩展集
关系表达式:可以用下面运算符表中的关系运算符进行操作,可以是字符串或数字的比较,如$2>$1   #选择第二个字段比第一个字段长的行


模式匹配表达式:
模式:指定一个行的范围,该语法不能包括BEGIN和END模式
BENGIN: 让用户指定在第一行输入记录被处理之前所发生的动作,通常可以在这里设置全局变量

action中可以使用的控制语句:
1.if-else
语法:if (condition) then-body [else-body]
例如: awk -F: '{if ($1=="root") print $1, "Admin"; else print $1, "Common User"}' /etc/passwd
awk -F: -v sum=0 '{if ($3>=500) sum ++}END{print sum}' /etc/passwd

2.while
语法:while (condition) {statement1;statement2;...}
例如:awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd

3.do-while
语法:do {statement1,statement2,...} while (condition)
例如:awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd

4.for
语法:for (variable assignment; condition; iteration process) {statement1;statement2;...}
例如:awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd

for循环还可以用来遍历数组元素;
语法:for (i in array) {statement1,statement2,...}
例如:awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH) {printf "%15s:%i\n",A,BASH[A]S}}' /etc/passwd

显示奇数段:awk -F: '{for(i=1;i<=NF;i+=2) print $i}' /etc/passwd
显示偶数段:awk -F: '{for(i=2;i<=NF,i+=2) print $i}' /etc/passwd

5.case
语法:switch (expression) {case VALUE or /REGRXP/: statement1,statement2,... default:statement1,...}

6.break 和 continue
常用于循环或case语句中

7.next
提前结束对本行文本的处理,并接着处理下一行;

###5,6,7不是很常用,这里不再举例说明


awk中使用数组:
array[index-expression]

index-expression 可以使用任意字符串,需要注意的是,如果某数据组元素事先不存在,那么在引用其时,awk会自动创建此元素并初始化为空串;因此,要判断某数据组中是否存在某元素,需要使用index in array的方式。

要遍历数组中的每个元素,需要使用如下的特殊结构:
for (var in array) {statement1,statement2...}
其中,var用于引用数组下标;

例如:统计某日志文件中IP的访问量
awk '{counts[$1]++};END {for (url in counts) print conuts[url],url}' /var/log/httpd/access_log

awk 'BEGIN{A[1]="hello";A[2]="world";print A[1],A[2]}'

统计tcp状态连接数:
 netstat -ant | awk '$1~/tcp/{S[$NF]++}{for (A in S) print A,S[A]}'