之前说过sed, 今天来说awk, 它也是一个文本处理器。 是linux下的一个命令, 比sed更强大。 搞linux开发, 尤其是后台开发, 这个命令差点儿必需要用到。 awk这三个字母分别代表其三位作者的名字, 而不是某个/某些有意义单词的缩写。

还是那句话,以实践操作为荣, 以仅仅看不练为耻。当然, 理解awk的原理是必须的:读入有'\n'换行符切割的一条记录,将记录按指定的域分隔符划分域,$0表示全部域, $1表示第一个域, $n表示第n个域。 默认域分隔符是空格键或tab键。

鉴于awk涉及的东西太多, 所以本文中, 我们只介绍主要的使用方法, 以后遇到了新的东东。 再加入到本博文中。 滚雪球似地积累。

先来感受一下awk, 我们如果test.txt中的内容:

xxx     Math English C++  Experiment
Monkey 100 90 95 Good
Cat 80 100 60 Perfect
Dog 90 60 70 Great
Tiger 95 85 90 Fantastic

之前。 我们用sed来输出行, 如今, 我们来感受一下用awk输出列, 例如以下:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{print $2}' test.txt
Math
100
80
90
95 Administrator@51B6904C3C8A485 ~/learn_awk
$

看到了吧, 这就是awk. 注意上面仅仅能是单引號, 不能是双引號, $2表示第二列。

我们来看看awk的一般格式:awk [option]  'pattern {action}' test.txt,  比方上面的awk '{print $2}' test.txt, 此时,採用默认选项。 且条件永远为真。

以下, 我们依据awk的原型来一一说明:

        A.awk 

事实上awk就相当于一个函数名, 没什么好说的了。

        B. option

我们先看例如以下操作。 打印test.txt文件的第二列:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{print $2}' test.txt
Math
100
80
90
95 Administrator@51B6904C3C8A485 ~/learn_awk

能够看到。 命令中没有选项, 也就是採用了默认选项, 如今如果a.txt中的文件内容为:

xxx|Math|English|C++|Experiment
Monkey|100|90|95|Good
Cat|80|100|60|Perfect
Dog|90|60|70|Great
Tiger|95|85|90|Fantastic

我们再用awk '{print $2}' a.txt就不灵了。 为什么呢? 由于awk '{print $2}' a.txt的选项为空, 默认的是以空格为分隔符, 显然不能进行划分。

那怎么办呢? 此时, 我们应该显式地指明分隔符。 例如以下:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk -F "|" '{print $2}' a.txt
Math
100
80
90
95 Administrator@51B6904C3C8A485 ~/learn_awk
$

这就对了。好了, 兴许我们仍然针对test.txt, 不针对a.txt. 也就是说。 採用默认的选项。

       C. pattern

这个最好理解了。 比方, 条件就是一种模式(但模式不不过条件, 有可能是一些正則表達式等)。我们看到。 在awk '{print $2}' test.txt中。 是无条件的, 所谓无条件即为真。

日本无条件投降。 大概就是这个意思。 当然。 为了讲清楚条件, 我们还是来看看:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '1<2 {print $2}' test.txt
Math
100
80
90
95 Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '1<1 {print $2}' test.txt Administrator@51B6904C3C8A485 ~/learn_awk
$

我们看到。 当条件为真的时候, 才会有真正的打印, 反之, 打个屁。

假设要打印整个文件。 能够这么搞:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '1' test.txt
xxx Math English C++ Experiment
Monkey 100 90 95 Good
Cat 80 100 60 Perfect
Dog 90 60 70 Great
Tiger 95 85 90 Fantastic Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '0' test.txt Administrator@51B6904C3C8A485 ~/learn_awk
$

能够看看到, 条件为真, 有打印。

否则, 没有打印。

       D. action

这个好理解。 无非就是内置命令而已, 比方print $2, 例如以下:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{print $2}' test.txt
Math
100
80
90
95 Administrator@51B6904C3C8A485 ~/learn_awk
$

当然, 假设你喜欢C/C++语言格式。 那全然能够写成:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{printf("%s\n", $2)}' test.txt
Math
100
80
90
95 Administrator@51B6904C3C8A485 ~/learn_awk
$

实际上。 在pattern部分, 我们是能够用C/C++语言的if等keyword的, 如:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{if(1<2) printf("%s\n", $2)}' test.txt
Math
100
80
90
95 Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{if(1<1) printf("%s\n", $2)}' test.txt Administrator@51B6904C3C8A485 ~/learn_awk
$

我们看到, awk看似非常小, 事实上五脏俱全。

弄清了上面的基本构成, awk就算基本入门了。 既然已经与awk有了初步的恋爱感觉了, 那就要趁热打铁的练习一下。

      一. awk的内置变量

1. $0表示整行, $n表示第n个分段。 例如以下:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{print $0}' test.txt
xxx Math English C++ Experiment
Monkey 100 90 95 Good
Cat 80 100 60 Perfect
Dog 90 60 70 Great
Tiger 95 85 90 Fantastic Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{print $2}' test.txt
Math
100
80
90
95 Administrator@51B6904C3C8A485 ~/learn_awk
$

再如:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{print $1, $3}' test.txt
xxx English
Monkey 90
Cat 100
Dog 60
Tiger 85 Administrator@51B6904C3C8A485 ~/learn_awk
$

2. FILENAME表示文件名。 比方:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{printf("%s\n", FILENAME)}' test.txt
test.txt
test.txt
test.txt
test.txt
test.txt Administrator@51B6904C3C8A485 ~/learn_awk
$

能够看到, 文件名称被打印出来了。 为什么是5个呢? 由于awk是逐行处理的。

3. NR是当前的行数, 能够理解为number of row, 当然, 假设你非要说now row这种中式英语。 那也能够。

总之。 你要明确。 NR非常实用。例如以下:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{printf("%d:%s\n", NR, FILENAME)}' test.txt
1:test.txt
2:test.txt
3:test.txt
4:test.txt
5:test.txt Administrator@51B6904C3C8A485 ~/learn_awk
$

那要创建test1.txt---test5.txt怎么搞呢? 也非常easy, 联合我们之前介绍过的xargs, 例如以下:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{printf("%s%d\n", FILENAME, NR)}' test.txt | xargs touch Administrator@51B6904C3C8A485 ~/learn_awk
$ ls
test.txt test.txt1 test.txt2 test.txt3 test.txt4 test.txt5 Administrator@51B6904C3C8A485 ~/learn_awk
$

4. FNR是文件里的行数。 和NR还是有点小小差别的。 且看:

Administrator@51B6904C3C8A485 ~/learn_awk
$ cp test.txt test_bak.txt Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{printf("%d:%d:%s\n", NR, FNR, FILENAME)}' test.txt test_bak.txt
1:1:test.txt
2:2:test.txt
3:3:test.txt
4:4:test.txt
5:5:test.txt
6:1:test_bak.txt
7:2:test_bak.txt
8:3:test_bak.txt
9:4:test_bak.txt
10:5:test_bak.txt Administrator@51B6904C3C8A485 ~/learn_awk
$

5. NF表示当前行有多少个段, 学这些东西的时候, 不要死记, 要知道NF是number of field的缩写, 那就清晰了。 例如以下:

Administrator@51B6904C3C8A485 ~/learn_awk
$ echo "good good study" | awk '{print NF}'
3 Administrator@51B6904C3C8A485 ~/learn_awk
$

可见有3个段, 以下我们看看test.txt的每行是不是有5个段:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{print NF}' test.txt
5
5
5
5
5 Administrator@51B6904C3C8A485 ~/learn_awk
$

果然如此。

6. FS是filed seperator, 也就是段切割符号, 默认情况下为空格, 以下我们不用默认的。 而用"|", 例如以下:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk -F "|" '{print FS}' test.txt
|
|
|
|
| Administrator@51B6904C3C8A485 ~/learn_awk
$

当然, 还有其它的一些内置变量, 在此就不一一举例了, 以后要用的时候, 一查便知。

      二. 常见的一些pattern

1. 条件式的pattern, 我们事实上已经熟悉了。 比方:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '1' test.txt
xxx Math English C++ Experiment
Monkey 100 90 95 Good
Cat 80 100 60 Perfect
Dog 90 60 70 Great
Tiger 95 85 90 Fantastic Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '1<=1' test.txt
xxx Math English C++ Experiment
Monkey 100 90 95 Good
Cat 80 100 60 Perfect
Dog 90 60 70 Great
Tiger 95 85 90 Fantastic Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '1<=0' test.txt Administrator@51B6904C3C8A485 ~/learn_awk
$

2. 来个复杂一点的条件pattern, 例如以下:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk 'length > 30' test.txt
xxx Math English C++ Experiment
Cat 80 100 60 Perfect
Dog 90 60 70 Great
Tiger 95 85 90 Fantastic Administrator@51B6904C3C8A485 ~/learn_awk
$

3. 继续条件pattern, 例如以下:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '$1=="Cat"' test.txt
Cat 80 100 60 Perfect Administrator@51B6904C3C8A485 ~/learn_awk
$

继续加个条件:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '$1!="Cat" && $3>=85' test.txt
xxx Math English C++ Experiment
Monkey 100 90 95 Good
Tiger 95 85 90 Fantastic Administrator@51B6904C3C8A485 ~/learn_awk
$

4. 打印第2-4行:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk 'NR>=2 && NR<=4 {print $0}' test.txt
Monkey 100 90 95 Good
Cat 80 100 60 Perfect
Dog 90 60 70 Great Administrator@51B6904C3C8A485 ~/learn_awk
$

别忘了, 我们的sed也能够, 也蛮牛逼的:

Administrator@51B6904C3C8A485 ~/learn_awk
$ sed -n "2,4"p test.txt
Monkey 100 90 95 Good
Cat 80 100 60 Perfect
Dog 90 60 70 Great Administrator@51B6904C3C8A485 ~/learn_awk
$

好了, 条件式的pattern我们介绍到这里。 以下我们介绍与正則表達式有关的一些pattern.

5. 行过滤, 类似于grep的功能。 如:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '/Cat/' test.txt
Cat 80 100 60 Perfect Administrator@51B6904C3C8A485 ~/learn_awk
$

对了,sed也有类似功能, 例如以下:

Administrator@51B6904C3C8A485 ~/learn_awk
$ sed -n "/Cat/"p test.txt
Cat 80 100 60 Perfect Administrator@51B6904C3C8A485 ~/learn_awk
$

6. 那能不能实现grep -v的功能呢? 肯定能够, 假设你觉得不能, 那太小看awk了, 且看:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '!/Cat/' test.txt
xxx Math English C++ Experiment
Monkey 100 90 95 Good
Dog 90 60 70 Great
Tiger 95 85 90 Fantastic Administrator@51B6904C3C8A485 ~/learn_awk
$

7. 输出以xxxxxx开头的行:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '/^C/' test.txt
Cat 80 100 60 Perfect Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '/^(C|D)/' test.txt
Cat 80 100 60 Perfect
Dog 90 60 70 Great Administrator@51B6904C3C8A485 ~/learn_awk
$

8. 输出以xxxxxx结尾的行:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '/t$/' test.txt
xxx Math English C++ Experiment
Cat 80 100 60 Perfect
Dog 90 60 70 Great Administrator@51B6904C3C8A485 ~/learn_awk
$

9. 自然而言地, 在一个pattern里, 我们能够既有正则又有条件, 如:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '/100/ && $4 >= 60' test.txt
Monkey 100 90 95 Good
Cat 80 100 60 Perfect Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '/100/ && $4 > 60' test.txt
Monkey 100 90 95 Good Administrator@51B6904C3C8A485 ~/learn_awk
$

10. 最后再来一个:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '/^x/, /^D/' test.txt
xxx Math English C++ Experiment
Monkey 100 90 95 Good
Cat 80 100 60 Perfect
Dog 90 60 70 Great Administrator@51B6904C3C8A485 ~/learn_awk
$

当然了。 sed肯定也有此功能。 不信你就翻翻我之前的博文。

       三. 常见的一些action, 实际上主要是内置函数

1. 最常见的print, printf, 例如以下:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{print $2}' test.txt
Math
100
80
90
95 Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{printf("%d\n", $2)}' test.txt
0
100
80
90
95 Administrator@51B6904C3C8A485 ~/learn_awk
$

2.  在action中也能够有种逻辑。 比方打印第2-4行:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{if(NR>=2 && NR<=4) print $0}' test.txt
Monkey 100 90 95 Good
Cat 80 100 60 Perfect
Dog 90 60 70 Great Administrator@51B6904C3C8A485 ~/learn_awk
$

当然, 你也能够把这个if条件移动到pattern中去, 如:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk 'NR>=2 && NR<=4 {print $0}' test.txt
Monkey 100 90 95 Good
Cat 80 100 60 Perfect
Dog 90 60 70 Great Administrator@51B6904C3C8A485 ~/learn_awk
$

3.  计算字符串长度, 相当于C/C++中的length函数

Administrator@51B6904C3C8A485 ~/learn_awk
$ echo "good good study" | awk '{print length}'
15 Administrator@51B6904C3C8A485 ~/learn_awk
$

再如:

Administrator@51B6904C3C8A485 ~/learn_awk
$ awk '{print length}' test.txt
36
30
33
31
35 Administrator@51B6904C3C8A485 ~/learn_awk
$

实际上, awk还有非常多内建的函数。 本文无法覆盖awk的全部内容。 只提供冰山一角的一些东东, 但供入门肯定是没有问题的。兴许会更依据实际, 对本文进行逐渐补充和完好。

肚子饿了。 该吃饭了。

awk基本使用方法简单介绍的更多相关文章

  1. InputStreamReader 和 OutputStreamWriter类使用方法简单介绍,及演示。

    InputStreamReader 和 OutputStreamWriter类使用方法简单介绍. 一.InputStreamReader类 InputStreamReader 将字节流转换为字符流.是 ...

  2. Android Mediaplayer各种属性和方法简单介绍

    主要涉及类:MediaPlayer (1) 当一个MediaPlayer对象被创建或者调用reset()方法之后,它处于空闲状态,调用release()方法后处于结束状态 1,一个MediaPlaye ...

  3. eclipse IDE使用git方法简单介绍

    eclipse下使用git插件上传代码至github 1.eclipse下安装git eclipse  git 插件的安装. 点击 Help->Install New Software-> ...

  4. java类中的static成员变量和static方法简单介绍,持续补充

    一.静态成员变量 1.属于整个类而不是某个对象实例,所以可以直接通过类名和对象名去调用. 2.静态成员属于整个类,当系统第一次使用该类时,就会为其分配内存空间直到该类被卸载才会进行资源回收 二.静态方 ...

  5. python 子进程 subpocess 的使用方法简单介绍

    python的子进程嘛,就是利用python打开一个子进程(当然像是一句废话),但是可能和我们理解的不太一样. 一:如何理解? 我们可能的理解:多开一个进程运行某个python函数(如果只想实现这个功 ...

  6. Python Appium 元素定位方法简单介绍

    Python  Appium  元素定位 常用的八种定位方法(与selenium通用) # id定位 driver.find_element_by_id() # name定位 driver.find_ ...

  7. java 多线程 start方法 run方法 简单介绍。

    一 start开启一个多线程, run 只是一个内部的方法. package com.aaa.threaddemo; /* * start方法的作用? * 在 Java中启动多线程调用的是start方 ...

  8. Java中的wait方法 简单介绍。

    一 wait方法怎么用? package com.aaa.threaddemo; /* * 多线程中的wait方法? public final void wait() throws Interrupt ...

  9. CFileDialog的使用方法简单介绍

    CFileDialog文件选择对话框的使用:首先构造一个对象并提供对应的參数,构造函数原型例如以下: CFileDialog::CFileDialog( BOOL bOpenFileDialog, L ...

随机推荐

  1. myBatis.xml文档实例

    单个参数:myBatis不会做特殊处理 #{参数名}: 取出参数值 多个参数: myBatis会做特殊处理 多个参数会被封装成一个MAP key:param1 param2.... param10,或 ...

  2. activemq常用配置

    所用版本为apache-activemq-5.15.4的版本 修改端口号 当端口号冲突时,可以修改这两个端口号.修改activemq.xml 修改里面的61616端口.修改jetty.xml,修改里面 ...

  3. POJ 2631 Roads in the North (求树的直径)

    Description Building and maintaining roads among communities in the far North is an expensive busine ...

  4. netcat命令的使用

    Linux netcat 命令实例: 1,端口扫描 端口扫描经常被系统管理员和黑客用来发现在一些机器上开放的端口,帮助他们识别系统中的漏洞. $nc -z -v -n 172.31.100.7 21- ...

  5. Triangular Pastures (二维01背包)

    描述Like everyone, cows enjoy variety. Their current fancy is new shapes for pastures. The old rectang ...

  6. Go 方法和接收者

    package main import ( "fmt" ) //面向对象 //go仅支持封装,不支持继承和多态 //go语言中没有class,只要struct //不论地址还是结构 ...

  7. [luoguP1169] [ZJOI2007]棋盘制作(单调栈)

    传送门 和玉蟾宫差不多 ——代码 #include <cstdio> #include <iostream> using namespace std; ; int n, m, ...

  8. ACDream:1210:Chinese Girls' Amusement【水题】

    Chinese Girls' Amusement Time Limit: 2000/1000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Oth ...

  9. 腾讯云CVM使用记录--使用root权限

    1.su root 指令 ,执行下列命令获取root权限: sudo /bin/su - root 注意:严禁执行password命令,root密码默认不能被修改.

  10. java Web项目Service层通用接口和entityVo对象与entity对象转化问题的解决方案

    Service层的接口中有一些比较常用方法,一次又一次的在新的Service层中被书写,所以懒惰的程序员又烦了,他们决定写个通用接口来解决这个问题. 有些项目中,实体类即承担接收表单数据的任务,又承担 ...