awk

怎么对一个文本进行格式化操作?如果使用的是windows,那么你的弄好半天,可是在linux上,我只能说so easy。对awk就敢这么说。超级强大

awk 不仅是一个命令,还是一门编程语言,能够实现条件判断,数组,循环等功能。以行为单位处理,将每一行以指定的分隔符分为多个分段,取出所需分段,以指定分隔符输出。

语法:

1
2
#第一种:program被单引号包围
awk [option] ‘program’ file
1
2
#第二种:分为模式和动作
awk [option] 'pattern option' file

awk 的两种写法中最常用的是第二种。

各部分参数

option常用选项:

1
2
-F		#define input field separator by extended regex,指定分隔符。容易记错,所以还是用-v FS=''指定内部变量比较好。
-v #assign values to variables,使用内部、外部变量。几乎每个awk命令都会用的一个参数

awk内置变量

1
2
3
4
5
6
7
8
9
FS	field separate ,输入字段分隔符,默认为空白字符
OFS output field separate,输出字段分隔符,默认为空白字符
RS record separate,输入记录分隔符,每一条记录(row)分隔的依据,默认为回车
ORS output record separate,输出记录分隔符,可以将多行合并为一行
NF number of field,字段数,$NF为最后一行
NR number of record,记录数(row),可以跟多个文件,文件的记录连续
FNR 可以跟多个文件,第二个文件记录数从一开始
ARGC 命令行参数个数
ARGV 命令行各参数组成的数组

例子:使用内部变量,指定输入字段分隔符

1
awk -v FS=':' '{print $1}' /etc/passwd

将多行合并为一行

1
awk -v ORS='' '{print $0}' /etc/passwd

使用外部变量

1
awk -v h=$HOST BEGIN'{print h}'  #BEGIN用来初始化变量

printf格式化输出

1
awk -v FS=':' '{printf "%-30s %-20s %-10s\n",$1,$2,$3}' /etc/passwd

%表示格式化输出

-减号表示左对齐,后面的数字表示变量所占用的宽度,变量没有占完的宽度用空白字符替代,可以实现真正的格式化输出

+加号表示右对齐。

\nprintf不会自动换行,需要手动加上

1
2
3
4
5
6
7
8
%c:  显示字符的ASCII码
%d %i: 显示十进制整数
%e %E: 显示科学计数法数值
%f :显示为浮点数,小数 %5.1f,带整数、小数点、整数共5位,小数1位,不够用空格补上
%g %G :以科学计数法或浮点形式显示数值
%s :显示字符串;例:%5s最少5个字符,不够用空格补上,超过5个还继续显示
%u :无符号整数
%%: 显示% 自身

操作符

算数操作符
1
+ - * / % ^
赋值操作符
1
+= -= *= /= %= ^=
比较操作符
1
== != > >= < <=
逻辑操作符
1
&& || !
模式匹配操作符
1
~ !~
三目操作符
1
selector?if-true-expression:if-false-expression
函数调用
1
function(args1,args2)

awk语句

除了指定一些变量外,其余内容的都应该写到括号里面,作为语句的一部分。awk的语法与c语言类似,语句间用分号相隔,同时变量不需要像shell中一样加$,直接使用变量名就行。语句块使用{}

if语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--- ~ » seq 10 | paste -s | awk '{if($3>2) print $0}'
1 2 3 4 5 6 7 8 9 10
--- ~ » seq 10 | paste -s | awk '{if($3<2){print $3} else if($4<3){print $4} else{print $5}}'
5
--- ~ » seq 10 | paste -s | awk '{if($3<2){
pipe pipe quote> print $3
pipe pipe quote> }
pipe pipe quote> else if($4<3){
pipe pipe quote> print $4
pipe pipe quote> }
pipe pipe quote> else{
pipe pipe quote> print $5
pipe pipe quote> }
pipe pipe quote> }‘
5

while循环

1
2
--- ~ » awk 'BEGIN{sum=0;i=1;while(i<=100){sum+=i;i++};print sum}'                                          
5050

for循环

1
2
--- ~ » awk 'BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i};print sum}'
5050

tips:awk循环中还可以使用break,continue,next等控制循环

至于其它功能,我觉得用处不大,所以不写了,有以上这些足够了。