十二、文件/目录-awk

king's blog
awk主要用于格式化报文、从文本文件中抽取数据包,下面着重讲述使用awk执行行操作及怎样从文本文件和字符串中抽取信息。

一、调用awk方式

方式1、默认分隔符

awk [-F field-separator] ‘commands’ input-file(s)
其中awk中模式使用空格作为[-F 域分隔符]

方式2、指定分隔符

awk -F: ‘commands’ input-file

方式3、将所有的awk命令插入一个单独文件,然后调用

备注:任何awk语句都由模式和动作组成
1.模式:可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段BEGIN和END
2.动作:在{}中指定,如打印语句,if等控制语句

二、应用举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#文件a.txt内容如下
weblogic@ETS157:/opt/project> cat a.txt
no name sex tel
1  a    m   110
2  b    f   120
3  c    m   114

#1.显示所有的内容,($0 ->表示所有域)
weblogic@ETS157:/opt/project> awk '{print $0}' a.txt | tee result.txt
no name sex tel
1  a    m   110
2  b    f   120
3  c    m   114

#2.显示第1、3列
weblogic@ETS157:/opt/project> awk '{print $1 "\t" $3}' a.txt | tee result.txt
no      sex
1       m
2       f
3       m

#3.显示第1列,并输出其他字符,如start,end
weblogic@ETS157:/opt/project> 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#1.匹配
weblogic@ETS157:/opt/project> awk '{if($4~/1/) print $0}' a.txt
1  a    m   110
2  b    f   120
3  c    m   114

weblogic@ETS157:/opt/project> awk '$0' a.txt
no name sex tel
1  a    m   110
2  b    f   120
3  c    m   114

weblogic@ETS157:/opt/project> awk '{if($2~/[ab]/) print $0 }' a.txt
no name sex tel
1  a    m   110
2  b    f   120

不特殊声明,awk将打印整条记录,如awk ‘$2 ~ /b/’ a.txt
但 awk ‘{$2 ~ /b/}’ a.txt 无结果输出,原因在于{}表示其中的是动作,此处并无任何动作,如print等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#2、精确匹配
weblogic@ETS157:/opt/project> awk '$4=="110" {print $0}' a.txt
1  a    m   110
weblogic@ETS157:/opt/project> awk '{if($2=="a" || $2=="b") print $0 }' a.txt
1  a    m   110
2  b    f   120
weblogic@ETS157:/opt/project> awk '{if($1>2) print $0}' a.txt
no name sex tel
3  c    m   114

#此处为关系匹配,匹配所有字段值为110或b,并打印所在行
weblogic@ETS157:/opt/project> awk '$0 ~ /(110|b)/' a.txt
1  a    m   110
2  b    f   120

备注:
1.用到的正则表达式字符为:\ ^ $ . [] | () * + ? <备注:每个符号的代表的意思>

  • + 使用+匹配一个或多个字符。
  • ? 匹配模式出现频率。例如使用/XY?Z/匹配XYZ或YZ。
  • ^ 代表行首

2.awk用到的条件表达式有< <= > >= == != ~ !~
3.逻辑表达式

  • && :语句两边必须同时匹配为真。
  • || :语句两边同时或其中一边匹配为真。
  • ! :非求逆

五:awk内置变量

1
2
3
4
5
6
7
8
9
10
11
ARGC     命令行参数个数
ARGV     命令行参数排列
ENVIRON  支持队列中系统环境变量的使用
FILENAME awk正在浏览的文件名
FNR      浏览文件的记录数
FS       设置输入域分隔符,等价于命令行- F选项
NF       浏览记录的域个数
NR       已读的记录数
OFS      输出域分隔符
ORS      输出记录分隔符
RS       控制记录分隔符

举例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#1.查看a.txt和b.txt文件的内容
weblogic@ETS157:/opt/project> cat a.txt
no name sex tel
1  a    m   110
2  b    f   120
3  c    m   114
weblogic@ETS157:/opt/project> cat b.txt
4 5  no name sex tel
4 6  10  a    m   110
4 7  20  b    f   120
4 8  30  c    m   114

#2.查看a.txt有多少行
weblogic@ETS157:/opt/project> awk 'END {print NR}' a.txt
4

#3.查看有多少域(NF),多少行数据(NR)等
weblogic@ETS157:/opt/project> 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
6 5      4 5  no name sex tel
6 6      4 6  10  a    m   110
6 7      4 7  20  b    f   120
6 8      4 8  30  c    m   114
b.txt

备注:

a.最强大的一个功能就是将变量$PWD的返回值传入awk并显示其目录,这里需要指定域分隔符/
如:echo $PWD | awk -F/ ‘{print $NF}’ -》返回当前所在的路径的目录名如 awk_file
b.显示文件名
如:echo “/opt/a/b/c” | awk -F/ ‘{print $NF}’ -> c

六、awk操作符

1
2
3
4
5
6
7
= += *= / = %= ^ = 赋值操作符
? 条件表达操作符
|| && ! 并、与、非
~!~ 匹配操作符,包括匹配和不匹配
< <= == != >> 关系操作符
+ - * / % ^ 算术操作符
+ + -- 前缀和后缀
1、设置输入域到域变量名
1
2
3
weblogic@ETS157:/opt/project> awk '{a=$1;c=$4;if(c ~ /120/) print a " tel is " c }' a.txt
2 tel is 120
说明:这里将$1的值赋给变量a;$4的值赋给变量c
2、域值的比较

方式一:直接使用实际值进行比较

1
2
3
weblogic@ETS157:/opt/project> awk '{if($1>2) print $0}' a.txt
no name sex tel
3  c    m   114

方式二:在BEGIN中使用变量

1
2
3
weblogic@ETS157:/opt/project> awk 'BEGIN {a="2"} {if($1>a) print $0}' a.txt
no name sex tel
3  c    m   114
3、修改数值域取值<只是修改awk的副本,不会修改原文件>
1
2
3
4
5
weblogic@ETS157:/opt/project> 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、修改文本域,也就是对其重新赋值
1
2
3
4
5
weblogic@ETS157:/opt/project> 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

七、内置的字符串函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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)只对第一次匹配到的项进行替换

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#1.
weblogic@ETS157:/opt/project> awk 'gsub(/1/,9) {print $0}' a.txt
9  a    m   990
2  b    f   920
3  c    m   994

#2.
weblogic@ETS157:/opt/project> awk 'gsub(/1/,9,$1) {print $0}' a.txt
9 a m 110

#3.
weblogic@ETS157:/opt/project> awk 'BEGIN {print index("abcce","c")}'
3
 
#4.
weblogic@ETS157:/opt/project> awk '$1=="1" {print length("abc"),"abc"}' a.txt
3 abc

#5.
weblogic@ETS157:/opt/project> awk 'BEGIN {print length("Hello World!")}'
12

#6.匹配到,并显示位置
weblogic@ETS157:/opt/project> awk 'BEGIN {print match("abcd","a")}'
1

weblogic@ETS157:/opt/project> awk 'BEGIN {print match("abcd","d")}'
4

weblogic@ETS157:/opt/project> awk 'BEGIN {print match("abcd","f")}'
0

weblogic@ETS157:/opt/project> awk 'BEGIN {print match("abcd","h")}'
0

weblogic@ETS157:/opt/project> awk 'BEGIN {print match("abcd",/c/)}'
3

#7.返回数组下标3,其中arr[1]="a" ; arr[2]="b" ; arr[3]="c"
weblogic@ETS157:/opt/project> awk 'BEGIN {print split("a#b#c",arr,"#")}'
3

#8.
weblogic@ETS157:/opt/project> awk 'sub(/1/,9) {print $0}' a.txt
9  a    m   110
2  b    f   920

#9.返回"abcd"中从第2个字符开始的前2个字符
weblogic@ETS157:/opt/project> awk 'BEGIN {print substr("abcd",2,2)}'
bc

#10.省略掉第三个参数,将从指定位置的字符开始,返回之后所有的字符
weblogic@ETS157:/opt/project> awk 'BEGIN {print substr("abcd",3)}'
cd

八、从shell中想awk传入字符串

1
2
3
4
5
6
7
8
weblogic@ETS157:/opt/project> echo "abcd" | awk 'gsub(/b/,"B")'
aBcd

weblogic@ETS157:/opt/project> echo "abcd" | awk '{print length($0)}'
4

weblogic@ETS157:/opt/project> 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 十六进制数

例子:

1
2
3
4
5
6
7
8
9
10
11
weblogic@ETS157:/opt/project> echo "65" | awk '{printf "%c\n",$0}'
A

weblogic@ETS157:/opt/project> awk 'BEGIN {printf "%f\n",99}'
99.000000

weblogic@ETS157:/opt/project> awk '{printf "%2s %2s\n",$1,$2}' a.txt
no name
 1  a
 2  b
 3  c

十、awk数组

1
2
weblogic@ETS157:/opt/project> awk 'BEGIN {print split("a#b#c",arr,"#")}'
3

十一、实际中的应用例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#1、查看该系统中的已注册的用户名
weblogic@ETS157:/opt/project> awk -F: '{print $1}' /etc/passwd
at
bin
daemon
ftp
...

#2、获取该目录下用户为root的文件,并记录到root_file.txt文件中
weblogic@ETS157:/opt> ll
total 20
drwxr-xr-x  7 root     root     4096 Nov  3  2014 kde3
drwxr-xr-x 30 oracle   oinstall 4096 Dec  7 13:52 oracle
drwxr-xr-x  3 root     root     4096 Nov  3  2014 ORCLfmap
drwxr-xr-x 14 weblogic wasgroup 4096 Feb 11 23:03 project
drwxr-xr-x  6 oracle   oinstall 4096 Nov  3  2014 Tools
weblogic@ETS157:/opt> ls -l | awk '{if($3=="root") print $9}'
kde3
ORCLfmap
Tags:
文 / 甲乙丙丁
LEAVE A REPLY

loading