博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux awk命令详解
阅读量:4041 次
发布时间:2019-05-24

本文共 5201 字,大约阅读时间需要 17 分钟。

awk :适用程序,一种unix工具

就是一个强大的文本分析工具,相对于grep查找、sed的编辑,awk在对数据分析并生成报告的时候,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种处理。

  • awk是用来操作数据和产生报表的一种编程语言。数据可能来自标准输入、一个或多个文件或一个进程的输出等。awk可以用在命令行里进行简单操作,也可应用到较大的应用程序中。
  • awk是一门编程语法,作为unix工具来使用简化了很多,但是仍然有许多编程语言的特性,可以对目标进行一系列的处理。
  • 如果抛出awk的BEGIN和END,对文件的每行,awk都分两个阶段处理:

    1、读取该行内容,分配临时寄存器,分配域名等操作;
    2、对域做各种处理并输出;

  • awk基本用途

    1、简单输出,如 awk ‘{print 1, NF}’ — print的规则
    2、作为分隔符使用
    单字符分隔符:打印系统中用户名和其他使用shell类型
    单字符分隔符,管道连续使用awk:打印nginx日志中的访问目录。
    多字符分隔符:抓取apache详细版本
    多字符多个分隔符:截取ip地址
    正则分隔符:截取ip地址

[root@admin test]# ls -ltotal 16-rw-r--r--. 1 root root    0 Jun 15 11:03 aa.jpg-rw-r--r--. 1 root root   12 Jun 15 10:48 ls.jpg-rw-r--r--. 1 root root  200 Jun 15 11:31 result.jpg-rw-r--r--. 1 root root    0 Jun 15 11:04 right.jpgdrwxr-xr-x. 2 root root 4096 Jun 20 06:39 sd.ex-rw-r--r--. 1 root root   49 Jun 15 11:04 wrong.jpg

通过awk打印出第一列:

[root@admin test]# ls -l | awk '{print $1}'total-rw-r--r--.-rw-r--r--.-rw-r--r--.-rw-r--r--.drwxr-xr-x.-rw-r--r--.

打印前两列,也就是前两个域:

[root@admin test]# ls -l | awk '{print $1,$2}'total 16-rw-r--r--. 1-rw-r--r--. 1-rw-r--r--. 1-rw-r--r--. 1drwxr-xr-x. 2-rw-r--r--. 1

在awk中,抛开BEGIN和END不看,’{}’ 这是一个固定写法。

$ : 符号表示域,域之间通过默认的分隔符 空格 分开,如果有多个空格就会变成一个空格,第一个域为$1,第二个为$2等…

打印最后一列:

[root@admin test]# ls -l | awk '{print $NF}'16aa.jpgls.jpgresult.jpgright.jpgsd.exwrong.jpg

$NF : 就代表最后一列的意思。

如果想打印倒数第二列,则使用$(NF -1)。

[root@admin test]# ls -l | awk '{print $(NF - 1)}'total11:0310:4811:3111:0406:3911:04

-F :参数-F是改变awk的默认分隔符,可以支持正则表达式。

[root@admin test]# ls -ltotal 16-rw-r--r--. 1 root root    0 Jun 15 11:03 aa.jpg-rw-r--r--. 1 root root   12 Jun 15 10:48 ls.jpg-rw-r--r--. 1 root root  200 Jun 15 11:31 result.jpg-rw-r--r--. 1 root root    0 Jun 15 11:04 right.jpgdrwxr-xr-x. 2 root root 4096 Jun 20 06:39 sd.ex-rw-r--r--. 1 root root   49 Jun 15 11:04 wrong.jpg

awk默认的分隔符是 空格,空格前一列就是$1,后面是$2,$3…..

当我们改变默认分隔符为 分号 “:”时,打印一下结果:

[root@admin test]# ls -l | awk -F":" '{print $NF}'total 1603 aa.jpg48 ls.jpg31 result.jpg04 right.jpg39 sd.ex04 wrong.jpg

通过-F 参数改变默认分隔符,以及其支持正则表达式的特性,精确的抽出ifconfig 文件中的ip地址。

#精确的抽取ip地址[root@admin test]# ifconfig | grep "inet addr" | awk -F "addr:|  *" '{print $4}'192.168.1.6127.0.0.1

分析:

grep "inet addr" 表示先抽取出含有ip的那行,然后通过管道交给awk去处理-F "addr:|  *" :表示该变默认分隔符为addr:或者连续多个空格$4 :表示改变默认分隔符以后,ip地址在第4个域。

用grep实现抽取ip :

[root@admin home]# ifconfig | egrep -o "[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"192.168.1.6192.168.1.255255.255.255.0127.0.0.1255.0.0.0

然后在用head和tail抽取想要的ip即可。

使用sed实现抽取ip

[root@admin home]# ifconfig |grep "inet addr" | sed 's/inet addr://' | sed 's/Bcast.*//' | head -1192.168.1.6或者:[root@admin home]# ifconfig |grep "inet addr" | sed 's/^.*addr://;s/  *.*//' | head -1192.168.1.6

awk匹配打印

注:需要匹配的内容是写在{}外面的,通过//来体现匹配。

匹配打印实际上是文件每行读取的时候做的处理。

1、整行中匹配内容

awk '/sth/{print $1}' ---打印匹配sth的行的第一个域,这是对整行进行操作awk '!/sth/{print $1}'  ---打印不匹配sth的行的第一个域

如匹配打印sd关键字:

[root@admin test]# lsaa.jpg  ls.jpg  result.jpg  right.jpg  sd.ex  wrong.jpg[root@admin test]# ls | awk '/sd/{print $1}'sd.ex

2、域匹配内容

匹配某个文件中以默认分隔符分隔的$1域中含有关键字sth的行,然后打印出第一个域,命令如下:

awk '$1~/sth/{print $1}'

3、改变awk中的默认分隔符

如打印出passwd文件中,以冒号 : 分隔的第一个域中含有关键字wcx行的第一个域:

[root@admin etc]# cat passwd | awk -F":" '$1~/wcx/{print $1}'wcx

awk判断打印

判断打印实际上是文件每行读取后做的处理。

格式例如:

awk '{if($1=="wcx")print $1}'

if 判断必须是进入某一行以后才能做的,所以必须是在花括号{} 里面。而模式匹配是先匹配到内容的行才能进行下一步操作,所以模式匹配实在花括号{}外边。

[root@admin etc]# cat ./passwd | awk -F ":" '{if($1 == "wcx")print}wcx:x:501:501::/home/wcx:/bin/bash

上面命令中,如果passwd文件中,以冒号分隔的第一个域==”wcx”,那么就打印出来,这是等于判断,所以只有wcx的行能出来。

BEGIN和END

在Unix awk中两个特别的表达式,BEGIN和END,这两者都可用于pattern中(参考前面的awk语法),提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。

任何在BEGIN之后列出的操作(在{}内)将在Unix awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。

awk的数组

有一个awk.txt文件,其内容如下:

[root@admin home]# cat awk.txtkk kekeajj d32jame 23srsrkkjamewcxjame

统计一下awk.txt文件中每个人名出现的次数:

[root@admin home]# cat awk.txt | awk '{a[$1]++}END{
for (i in a)print i,a[i]}'wcx 1jj 1kk 2sr 2jame 3

解题思路分析:

{a[$1]++} :awk开始扫描管道传过来的内容,但是么有存储功能,现在我们需要计算每个人名出现的额次数,所以需要把扫描到的相同的人名分别存储起来,这时候就必须用数组,并且这里的数组都是hash数组,就是键值对的数组,这里的键—对应的就是对应域中的人名,如kk,值 — 对应的就是kk这个人名出现的次数。数组a中的下标$1代表的是第一个域中列名,如wcx。awk开始逐行扫描,每扫到一个相同的人名,对应的hash数组里的值就+1,如a[kk]++,直到扫到文件的结尾。(注:数组的默认值为空,如果要做++操作了,就会把里的值变成0)

END : END之后列出的操作将在Unix awk开始扫描完全部的输入之后执行。上面扫描完以后,就开始执行END后面的操作了。

{for (i in a)print i,a[i]} :利用for循环去遍历刚刚产生的hash数组,然后打印出数组下标所代表的值,也就是人名以及对数组中的值,也就是对应人名出现的次数。这里的i,就代表数组的下标,也就是域中的人名,如kk。

awk输出分隔符

awk默认的输出分隔符也是空格,如果想改变默认输出分隔符怎么做?

[root@admin home]# cat awk.txt | awk '{print $1,$2}'kk kekeajj d32jame 23sr 234sr edrkk 23jame rtwcx 88jame 34

运行结果看出,打印时,$1和$2间加了逗号以后,输出的文本中域间就都是用空格隔开的。

如果我不加逗号,改为加一串别的字符时,输出后就以加入的字符作为分隔符了。如:

[root@admin home]# cat awk.txt | awk '{print $1"--"$2"BB"}'kk--kekeaBBjj--d32BBjame--23BBsr--234BBsr--edrBBkk--23BBjame--rtBBwcx--88BBjame--34BB

通过awk批量修改扩展名

[root@admin test]# lsaa.jpg  ls.jpg  result.jpg  right.jpg  wrong.jpg

将test目录下的以.jpg结尾的文件改成.txt结尾的文件:

[root@admin test]# ls | awk -F "." '{print "mv "$1"."$2" "$1".txt"}'|sh[root@admin test]# lsaa.txt  ls.txt  result.txt  right.txt  wrong.txt或者:[root@admin test]# ls | awk -F "." '{print "mv "$0" "$1".txt"}' | sh#$0表示整行的内容

思路分析,同样改名也是需要构造mv a.txt a.jpg这样类似的语句的,这就用到了上面讲的输出时修改默认分隔符的操作了。构造出的mv语句再传给sh去执行就可以实现改名的操作。

转载地址:http://icmdi.baihongyu.com/

你可能感兴趣的文章
苹果Swift编程语言入门教程【中文版】
查看>>
捕鱼忍者(ninja fishing)之游戏指南+游戏攻略+游戏体验
查看>>
iphone开发基础之objective-c学习
查看>>
iphone开发之SDK研究(待续)
查看>>
计算机网络复习要点
查看>>
Variable property attributes or Modifiers in iOS
查看>>
NSNotificationCenter 用法总结
查看>>
C primer plus 基础总结(一)
查看>>
剑指offer算法题分析与整理(一)
查看>>
剑指offer算法题分析与整理(三)
查看>>
Ubuntu 13.10使用fcitx输入法
查看>>
pidgin-lwqq 安装
查看>>
mint/ubuntu安装搜狗输入法
查看>>
C++动态申请数组和参数传递问题
查看>>
opencv学习——在MFC中读取和显示图像
查看>>
retext出现Could not parse file contents, check if you have the necessary module installed解决方案
查看>>
Matlab与CUDA C的混合编程配置出现的问题及解决方案
查看>>
如何将PaperDownloader下载的文献存放到任意位置
查看>>
C/C++中关于动态生成一维数组和二维数组的学习
查看>>
JVM最简生存指南
查看>>