随便新建一个文件内容如下
ly@LY-Think:~$ cat test.txt
zxc/100/http
qwe/111/linux
url/111/window
asd/120/macos
clu/113/www
bdf/101/unix
awk读取文本的方式为逐行扫描,这里采用了三种方式打印test.txt中的内容,第一中是采用'{print}',不接$0参数,因为不接参数默认是$0, 所以接$0和不接$0都是代表一个意思,而$0的含义是一整行的意思,所以采用$0会打印整行内容,而awk又是按行处理文本的,在打印完第一行的时候就传入第二行,然后开始对第二行进行处理,直到所有行都处理完.命令的结果便是逐行扫描,然后打印一行,直到所有行打印完毕,最终结果就是打印整个文本文件.awk不仅可以从文件读取输入还可以从标准输出中读取数据.
ly@LY-Think:~$ awk '{print}' test.txt
zxc/100/http
qwe/111/linux
url/111/window
asd/120/macos
clu/113/www
bdf/101/unix
ly@LY-Think:~$ awk '{print $0}' test.txt
zxc/100/http
qwe/111/linux
url/111/window
asd/120/macos
clu/113/www
bdf/101/unix
ly@LY-Think:~$ cat test.txt | awk '{print $0}'
zxc/100/http
qwe/111/linux
url/111/window
asd/120/macos
clu/113/www
bdf/101/unix
awk打印指定字段,所谓字段就是以某个符号作为分隔符,将一串字符串分开,分开后的每一段就叫一个字段,比如本文中就采用/作为字段分隔符,字段分隔符可以是特殊符号,也可以是数字或者字母,选择了分隔符后分隔符将不会出现在输出中,相当于分隔符两端被剪断了,然后把分隔符拿走了,剩下的一段段的字符串才是我们要操作的,awk -F '/' 中的-F表示指定分隔符,至于分隔符/为什么要用单引号是防止linux终端shell将分隔符解释为特殊意义,举个例子,linux中的$被解释为变量标志,假如文中有$并且我们刚好就要用$作为分隔符,不加''号就会出差,至于不用""号的原因是因为""中的$也会被当成变量标志,综合考虑用''号最合适,其实如果不是linux中的一些特殊字符不加''也可以
ly@LY-Think:~$ cat test.txt | awk -F '/' '{print $1,$2}'
zxc 100
qwe 111
url 111
asd 120
clu 113
bdf 101
ly@LY-Think:~$ cat test.txt | awk -F / '{print $1,$2}'
zxc 100
qwe 111
url 111
asd 120
clu 113
bdf 101
awk的强大之处是对正则表达式的支持,正则表达式一般放于两斜杠/正则表达式/之间,下面演示了通过正则表达式,找出以a开头 , b开头 或者a开头和b开头的行,并且以/为分隔符,打印匹配该条件的第1字段和第2字段,注意'/^a|^b/{print $1,$2}'这句有个|符号,这个是运算符或的意思,此时就体现了前面所说的单引号的作用了,|不会被shell翻译成管道符
ly@LY-Think:~$ cat test.txt | awk -F / '/^a/{print $1,$2}'
asd 120
ly@LY-Think:~$ cat test.txt | awk -F / '/^b/{print $1,$2}'
bdf 101
ly@LY-Think:~$ cat test.txt | awk -F / '/^a|^b/{print $1,$2}'
asd 120
bdf 101
awk还可以指定对哪个字段操作,例如下列例子,首先从管道符获取标准输入,然后指定分隔符为/,进行字段分割,分割后的字段执行单引号里的操作,从'$2==111 {print $3}'分析程序,$2==111将会把分割后的字段进行筛选,选择第二个字段值等于111的行,然后打印该行的第3个字段
ly@LY-Think:~$ cat test.txt
zxc/100/http
qwe/111/linux
url/111/window
asd/120/macos
clu/113/www
bdf/101/unix
ly@LY-Think:~$ cat test.txt | awk -F '/' '$2==111{print $1}'
qwe
url
ly@LY-Think:~$ cat test.txt | awk -F '/' '$2>111 {print $1}'
asd
clu
ly@LY-Think:~$ cat test.txt | awk -F '/' '$2<111 {print $3}'
http
unix
经过一番了解,发现awk中的'{print}'有点像Python2的语法,Python2中的print函数允许你不写(),但是在Python3中就不行必须以这种形式print(), 从下面这条语句可以看出awk也是可以直接在print函数中进行加减乘除(字符串不太行,可以试试,这点与python2又有些差异)
ly@LY-Think:~$ cat t.txt
10 20 30
40 50 60
ly@LY-Think:~$ cat t.txt | awk '{print $1+$2,$2*$3}'
30 600
90 3000
用awk筛选出字段后结合sort进行排序,不得不说管道符的强大,从左边开始,管道符会依次将最左边的输入作为下一个管道符后的命令的输入,以至于我们可以无限连招,sort不带参数的时候应该是这样的sort -n n表示自然数,不带参数将会按从小到大排序,而sort -r则是反向排序,也就是从大到小排序,这里的r是单词Reverse(反向)的首字母,可以看出linux中好多参数有可能就是其单词意思的首字母,也是挺好记的,不记得怎倒序你就想想反向的单词,不记得按自然数排序你就想想nature的单词
ly@LY-Think:~$ cat test.txt | awk -F '/' '{print $2}' | sort
100
101
111
111
113
120
ly@LY-Think:~$ cat test.txt | awk -F '/' '{print $2}' | sort -n
100
101
111
111
113
120
ly@LY-Think:~$ cat test.txt | awk -F '/' '{print $2}' | sort -r
120
113
111
111
101
100
排序完之后还能去重,去重必须要在排序完之后,因为排序完之后相同的会相邻在一起,这样才能达到去重效果,具体原因不详,去重更容易记住,直接就是单词本意uniq,如果你用的是我这个例子,那么你不排序也可以去重,因为默认输出两个111就挨在一起了,要尝试自己写多几条相同数据而且不要相邻,再试试,这样就能验证
ly@LY-Think:~$ cat test.txt | awk -F '/' '{print $2}' | sort -n
100
101
111
111
113
120
ly@LY-Think:~$ cat test.txt | awk -F '/' '{print $2}' | sort -n | uniq
100
101
111
113
120
去重后还能干嘛呢?你以为到这里就没了吗,去完重复的还可以统计一下每一条数据有多少重复的,第一个字段就是重复的数量,这里的uniq -c也很好记,c是count(计数)单词的首字母
ly@LY-Think:~$ cat test.txt | awk -F '/' '{print $2}' | sort -n | uniq -c
1 100
1 101
2 111
1 113
1 120
未完待续...这还没完成我的目标,我的目标是打印出出现2次的字段是哪个,或者打印出出现次数大于1次的字段或者次数,再次完美连招,对于查看log很有帮助
ly@LY-Think:~$ cat test.txt | awk -F '/' '{print $2}' | sort -n | uniq -c | awk '$1>1 {print $1}'
2
ly@LY-Think:~$ cat test.txt | awk -F '/' '{print $2}' | sort -n | uniq -c | awk '$1>1 {print $2}'
111
ly@LY-Think:~$ cat test.txt | awk -F '/' '{print $2}' | sort -n | uniq -c | awk '$1==2 {print $2}'
111
ly@LY-Think:~$ cat test.txt | awk -F '/' '{print $2}' | sort -n | uniq -c | awk '$1==2 {print $1}'
2