awk主要用于格式化报文、从文本文件中抽取数据包,下面着重讲述使用awk执行行操作及怎样从文本文件和字符串中抽取信息。
一、调用awk方式
1、awk [-F field-separator] 'commands' input-file(s)
awk中模式使用空格作为[-F 域分隔符]
2、awk -F: 'commands' input-file
3、将所有的awk命令插入一个单独文件,然后调用
任何awk语句都由模式和动作组成
模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段BEGIN和END
动作在{}中指定,如打印语句,if等控制语句
二、应用举例
文件a.txt内容如下:
no name sex tel
1 a m 110
2 b f 120
3 c m 114
awk '{print $0}' a.txt | tee result.txt ($0 ->表示所有域)
结果:显示所有的内容
awk '{print $1 "\t" $3}' a.txt | tee result.txt
结果:显示第1、3列
awk ' BEGIN {print "start\n---"} {print $1} END {print "---\nend"} ' a.txt | tee result.txt
结果:
start
---
no
1
2
3
---
end
三、注意事项
确保整个awk命令用单引号括起来。
确保命令内所有引号成对出现。
确保用花括号括起动作语句,用圆括号括起条件语句。
可能忘记使用花括号,也许你认为没有必要,但awk不这样认为,将按之解释语法
四、awk与正则表达式和条件表达式的结合
1、匹配
awk '{if($4~/1/) print $0}' a.txt
或 awk '$0' a.txt ->
1 a m 110
2 b f 120
3 c m 114
awk '$0 ~/4/' a.txt ->
3 c m 114
awk '{if($2~/[ab]/) print $0 }' a.txt ->
1 a m 110
2 b f 120
不特殊声明,awk将打印整条记录,如awk '$2 ~ /b/' a.txt
但 awk '{$2 ~ /b/}' a.txt 无结果输出,原因在于{}表示其中的是动作,此处并无任何动作,如print等
2、精确匹配
awk '$4=="110" {print $0}' a.txt ->
1 a m 110
awk '{if($2=="a" || $2=="b") print $0 }' a.txt ->
1 a m 110
2 b f 120
awk '{if($1>2) print $0}' a.txt -》
3 c m 114
awk '$0 ~ /(110|b)/' a.txt -> 此处为关系匹配,匹配所有字段值为110或b,并打印所在行
1 a m 110
2 b f 120
备注:
1.用到的正则表达式字符为:\ ^ $ . [] | () * + ? <备注:每个符号的代表的意思>
+ 使用+匹配一个或多个字符。
? 匹配模式出现频率。例如使用/XY?Z/匹配XYZ或YZ。
^ 代表行首
2.awk用到的条件表达式有< <= > >= == != ~ !~
3.逻辑表达式
&& :语句两边必须同时匹配为真。
|| :语句两边同时或其中一边匹配为真。
! :非求逆
五:awk内置变量
ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON支持队列中系统环境变量的使用
FILENAME awk正在浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行- F选项
NF 浏览记录的域个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符
举例:
awk 'END {print NR}' a.txt -> 4
awk '{print NF,NR,"\t",$0} END {print FILENAME}' a.txt b.txt ->
4 1 no name sex tel
4 2 1 a m 110
4 3 2 b f 120
4 4 3 c m 114
4 5 no name sex tel
4 6 10 a m 110
4 7 20 b f 120
4 8 30 c m 114
b.txt
NF:
a.最强大的一个功能就是将变量$PWD的返回值传入awk并显示其目录,这里需要指定域分隔符/
如:echo $PWD | awk -F/ '{print $NF}' -》返回当前所在的路径的目录名如 awk_file
b.显示文件名
如:echo "/opt/a/b/c" | awk -F/ '{print $NF}' -> c
六、awk操作符
= += *= / = %= ^ = 赋值操作符
? 条件表达操作符
|| && ! 并、与、非
~!~ 匹配操作符,包括匹配和不匹配
< <= == != >> 关系操作符
+ - * / % ^ 算术操作符
+ + -- 前缀和后缀
1、设置输入域到域变量名
awk '{a=$1;c=$4;if(c ~ /120/) print a " tel is " c }' a.txt
-> 2 tel is 120
说明:这里将$1的值赋给变量a;$4的值赋给变量c
2、域值的比较
方式一:直接使用实际值进行比较
awk '{if($1>2) print $0}' a.txt
awk '{$1>2}' a.txt
返回:
no name sex tel
3 c m 114
方式二:在BEGIN中使用变量
awk 'BEGIN {a="2"} {if($1>a) print $0}' a.txt -》同上
3、修改数值域取值<只是修改awk的副本,不会修改原文件>
如: awk '{if($2=="a") $1=$1+1 ; print $0}' a.txt ->
no name sex tel
2 a m 110 -> 此行的no已经+1
2 b f 120
3 c m 114
4、修改文本域,也就是对其重新赋值
如: awk '{if($2=="a") ($2="W") ; print $0}' a.txt ->
no name sex tel
1 W m 110 -> 此行的name已被修改为W
2 b f 120
3 c m 114
七、内置的字符串函数
gsub( r, s ) 在整个$0中用s替代r
gsub( r, s , t ) 在整个t中用s替代r
index( s , t ) 返回s中字符串t的第一位置
length( s ) 返回s长度
match( s , r ) 测试s是否包含匹配r的字符串
split( s , a , fs ) 在fs上将s分成序列a
sprint( f m t , e x p ) 返回经f m t格式化后的e x p
sub( r, s ) 用$0中最左边最长的子串代替s
substr( s , p ) 返回字符串s中从p开始的后缀部分
substr( s , p , n ) 返回字符串s中从p开始长度为n的后缀部分
gsub函数有点类似于s e d查找和替换。它允许替换一个字符串或字符为另一个字符串
备注:gsub(r,s)和sub(r,s)的区别:
gsub(r,s)对$0中所有的匹配项进行替换
sub(r,s)只对第一次匹配到的项进行替换
例:
awk 'gsub(/1/,9) {print $0}' a.txt ->返回
9 a m 990
2 b f 920
3 c m 994
awk 'gsub(/1/,9,$1) {print $0}' a.txt ->返回
9 a m 110
awk 'BEGIN {print index("abcce","c")}' ->返回
3
awk '$1=="1" {print length("abc"),"abc"}' a.txt ->返回
3 abc
awk 'BEGIN {print length("Hello World!")}' ->返回
12
#awk 'BEGIN {print match("abcd","a")}' ->匹配到,并显示位置
1
#awk 'BEGIN {print match("abcd","d")}'
4
#awk 'BEGIN {print match("abcd","f")}' ->未匹配到
0
#awk 'BEGIN {print match("abcd","h")}'
0
# awk 'BEGIN {print match("abcd",/c/)}'
3
# awk 'BEGIN {print split("a#b#c",arr,"#")}' ->返回数组下标3
3 其中arr[1]="a" ; arr[2]="b" ; arr[3]="c"
#awk 'sub(/1/,9) {print $0}' a.txt ->
9 b f 120
#awk 'BEGIN {print substr("abcd",2,2)}' ->返回"abcd"中从第2个字符开始的前2个字符
bc
#awk 'BEGIN {print substr("abcd",3)}' ->省略掉第三个参数,将从指定位置的字符开始,返回之后所有的字符
cd
八、从shell中想awk传入字符串
echo "abcd" | awk 'gsub(/b/,"B")' -> aBcd
echo "abcd" | awk '{print length($0)}' ->4
STR="abc.txt"
echo $STR | awk '{print substr($STR,1,5)}' ->abc.t
九、awk输出函数printf
- 左对齐
width域的步长,用0表示0步长
.prec最大字符串长度,或小数点右边的位数
%c ascii字符
%d 整数
%e 浮点数,科学记数法
%f 浮点数,例如(123.44)
%g awk决定使用哪种浮点数转换e或者f
%o 八进制数
%s 字符串
%x 十六进制数
echo "65" | awk '{printf "%c\n",$0}' ->A
awk 'BEGIN {printf "%f\n",99}' ->99.000000
awk '{printf "%2s %2s\n",$1,$2}' a.txt ->
no name
1 a
2 b
3 c
十、awk数组
awk 'BEGIN {print split("a#b#c",arr,"#")}' -> 3
十一、实际中的应用例子
1、查看该系统中的已注册的用户名
awk -F: '{print $1}' /etc/passwd
2、获取该目录下用户为root的文件,并记录到root_file.txt文件中
ls -l | awk '{if($3=="root") print $9}'