本文转自chinaunix http://bbs.chinaunix.net/thread-4246512-1-1.html   作者reyleon

我们知道, awk程序由一系列 pattern 以及与之对应的 action 组成的 rule 组成,rule之间用";"分号隔开, 一条输入记录与 pattern 匹配则执行与之关联的action, 如下所示:

awk ' 
        pattern { action };
        pattern { action };
        .....
'

可是, 很多人并不清楚什么东西可以做为 pattern下面就来聊聊这些个事儿. 以下文本做为测试文本:

 1 $ cat myfile2 Amelia     555-5553  amelia.zodiacusque@gmail.com     F3 Anthony    555-3412  anthony.asserturo@hotmail.com    A4 Becky      555-7685  becky.algebrarum@gmail.com       A5 Bill       555-1675  bill.drowning@hotmail.com        A6 Broderick  555-0542  broderick.aliquotiens@yahoo.com  R7 Camilla    555-2912  camilla.infusarum@skynet.be      R8 Fabius     555-1234  fabius.undevicesimus@ucb.edu     F9 Julie      555-6699  julie.perscrutabor@skeeve.com    F
10 Martin     555-6480  martin.codicibus@hotmail.com     A
11 Samuel     555-3430  samuel.lanceolis@shu.edu         A
12 Jean-Paul  555-2127  jeanpaul.campanorum@nyu.edu      R

首先, 要记住, 凡是被 {} 包裹的, 就是 action, 或者说, action 必然被 {} 包裹着
凡是没有被{}包裹的, 就是pattern, 或者说pattern不能被{}包裹着.

一. 正则表达式做为 pattern

最常见的, 就是一个正则表达式做为一个 pattern了, 如:

1 awk '/555-5553/ { print $0 }' myfile

/555-5553/ 就是一个正则表达式, 如果输入记录匹配555-5553, 就输出这条记录, 这里只有第一行匹配 555-5553, 所以就输出了第一行这条记录.

1 $ awk '/555-5553/ { print $0 }' myfile
2 Amelia     555-5553  amelia.zodiacusque@gmail.com     F

二. 比较表达式做为 pattern

1 $ awk '$NF == "A" { print $0 }' myfile
2 Anthony    555-3412  anthony.asserturo@hotmail.com    A
3 Becky      555-7685  becky.algebrarum@gmail.com       A
4 Bill       555-1675  bill.drowning@hotmail.com        A
5 Martin     555-6480  martin.codicibus@hotmail.com     A

最后一个字段为 "A" 的, 输出这条记录.

1 $ awk '$NF != "A" { print $0 }' myfile
2 Amelia     555-5553  amelia.zodiacusque@gmail.com     F
3 Broderick  555-0542  broderick.aliquotiens@yahoo.com  R
4 Camilla    555-2912  camilla.infusarum@skynet.be      R
5 Fabius     555-1234  fabius.undevicesimus@ucb.edu     F
6 Julie      555-6699  julie.perscrutabor@skeeve.com    F
7 Jean-Paul  555-2127  jeanpaul.campanorum@nyu.edu      R

最后一个字段不为 "A" 的, 输出这条记录.

三. 常量表达式做为 pattern

这种pattern一般是最不易被新手理解的, 事实上, 既然是 pattern 匹配, 结果就只有两种情况, 要么匹配(即为真),就执行后面的 action, 要么不匹配(即为假), 就不会执行后面的action.
所以, awk 的规则基本上也就是:

awk ' 真 { 执行代码 }; 假 { 不执行代码 }'

也理解为:

awk ' 条件 { 动作 } 条件 { 动作 } '

什么东西可以做为一个常量? 一个数字, 或者一个字符串, 都可以做为一个常量 pattern. 那这里就有一个龟腚了:

凡是非0的数字, 就表示pattern匹配成功, 也就是pattern为真. 否则表示匹配失败, 为假.
凡是非空的字符串, 就表示pattern匹配成功, 也就是pattern为真. 否则表示匹配失败, 为假.

注意: 字符串是由引号引起来的! 比如数字 0 与 字符串 "0" 不是一样的. 数字0为假, 字符串"0"为真(不为空).

如:

 1 $ awk '1 { print $0 }' myfile2 Amelia     555-5553  amelia.zodiacusque@gmail.com     F3 Anthony    555-3412  anthony.asserturo@hotmail.com    A4 Becky      555-7685  becky.algebrarum@gmail.com       A5 Bill       555-1675  bill.drowning@hotmail.com        A6 Broderick  555-0542  broderick.aliquotiens@yahoo.com  R7 Camilla    555-2912  camilla.infusarum@skynet.be      R8 Fabius     555-1234  fabius.undevicesimus@ucb.edu     F9 Julie      555-6699  julie.perscrutabor@skeeve.com    F
10 Martin     555-6480  martin.codicibus@hotmail.com     A
11 Samuel     555-3430  samuel.lanceolis@shu.edu         A
12 Jean-Paul  555-2127  jeanpaul.campanorum@nyu.edu      R

 1 $ awk '2 { print $0 }' myfile2 Amelia     555-5553  amelia.zodiacusque@gmail.com     F3 Anthony    555-3412  anthony.asserturo@hotmail.com    A4 Becky      555-7685  becky.algebrarum@gmail.com       A5 Bill       555-1675  bill.drowning@hotmail.com        A6 Broderick  555-0542  broderick.aliquotiens@yahoo.com  R7 Camilla    555-2912  camilla.infusarum@skynet.be      R8 Fabius     555-1234  fabius.undevicesimus@ucb.edu     F9 Julie      555-6699  julie.perscrutabor@skeeve.com    F
10 Martin     555-6480  martin.codicibus@hotmail.com     A
11 Samuel     555-3430  samuel.lanceolis@shu.edu         A
12 Jean-Paul  555-2127  jeanpaul.campanorum@nyu.edu      R

1 $ awk '0 { print $0 }' myfile
2 // 数字 0 做为 pattern, 0为假, pattern 匹配失败, 所以不执行 print $0, 没有打印.

 1 $ awk ' "0" { print $0 }' myfile2 Amelia     555-5553  amelia.zodiacusque@gmail.com     F3 Anthony    555-3412  anthony.asserturo@hotmail.com    A4 Becky      555-7685  becky.algebrarum@gmail.com       A5 Bill       555-1675  bill.drowning@hotmail.com        A6 Broderick  555-0542  broderick.aliquotiens@yahoo.com  R7 Camilla    555-2912  camilla.infusarum@skynet.be      R8 Fabius     555-1234  fabius.undevicesimus@ucb.edu     F9 Julie      555-6699  julie.perscrutabor@skeeve.com    F
10 Martin     555-6480  martin.codicibus@hotmail.com     A
11 Samuel     555-3430  samuel.lanceolis@shu.edu         A
12 Jean-Paul  555-2127  jeanpaul.campanorum@nyu.edu      R
13 // 字符串 "0" 做为 pattern, 为真, pattern 匹配成功, 所以执行 print $0, 打印.

还有一些, 可能是写错的赋值语句做为了pattern的, 或者其他乱七八糟的, 等等..:

1 $ awk 'a=0'  myfile // 数字0. 假, 没输出.

 1 $ awk 'a=1'  myfile // 1 为真. 2 Amelia     555-5553  amelia.zodiacusque@gmail.com     F3 Anthony    555-3412  anthony.asserturo@hotmail.com    A4 Becky      555-7685  becky.algebrarum@gmail.com       A5 Bill       555-1675  bill.drowning@hotmail.com        A6 Broderick  555-0542  broderick.aliquotiens@yahoo.com  R7 Camilla    555-2912  camilla.infusarum@skynet.be      R8 Fabius     555-1234  fabius.undevicesimus@ucb.edu     F9 Julie      555-6699  julie.perscrutabor@skeeve.com    F
10 Martin     555-6480  martin.codicibus@hotmail.com     A
11 Samuel     555-3430  samuel.lanceolis@shu.edu         A
12 Jean-Paul  555-2127  jeanpaul.campanorum@nyu.edu      R

 1 $ awk 'x-1'  myfile // x 为未定义的变量, 做数学运算, 结果为 -1 , 因 -1 也是非0的数字常量, pattern 匹配成功, 为真, print $0.2 Amelia     555-5553  amelia.zodiacusque@gmail.com     F3 Anthony    555-3412  anthony.asserturo@hotmail.com    A4 Becky      555-7685  becky.algebrarum@gmail.com       A5 Bill       555-1675  bill.drowning@hotmail.com        A6 Broderick  555-0542  broderick.aliquotiens@yahoo.com  R7 Camilla    555-2912  camilla.infusarum@skynet.be      R8 Fabius     555-1234  fabius.undevicesimus@ucb.edu     F9 Julie      555-6699  julie.perscrutabor@skeeve.com    F
10 Martin     555-6480  martin.codicibus@hotmail.com     A
11 Samuel     555-3430  samuel.lanceolis@shu.edu         A
12 Jean-Paul  555-2127  jeanpaul.campanorum@nyu.edu      R

1 1 $ awk 'xxoo'  myfile //xxoo为变量, 未赋值, 为假

 1 $ awk '"xxoo"'  myfile // 字符串, 真.2 Amelia     555-5553  amelia.zodiacusque@gmail.com     F3 Anthony    555-3412  anthony.asserturo@hotmail.com    A4 Becky      555-7685  becky.algebrarum@gmail.com       A5 Bill       555-1675  bill.drowning@hotmail.com        A6 Broderick  555-0542  broderick.aliquotiens@yahoo.com  R7 Camilla    555-2912  camilla.infusarum@skynet.be      R8 Fabius     555-1234  fabius.undevicesimus@ucb.edu     F9 Julie      555-6699  julie.perscrutabor@skeeve.com    F
10 Martin     555-6480  martin.codicibus@hotmail.com     A
11 Samuel     555-3430  samuel.lanceolis@shu.edu         A
12 Jean-Paul  555-2127  jeanpaul.campanorum@nyu.edu      R

四. 空 pattern

 1 $ awk '{print $0}' myfile2 Amelia     555-5553  amelia.zodiacusque@gmail.com     F3 Anthony    555-3412  anthony.asserturo@hotmail.com    A4 Becky      555-7685  becky.algebrarum@gmail.com       A5 Bill       555-1675  bill.drowning@hotmail.com        A6 Broderick  555-0542  broderick.aliquotiens@yahoo.com  R7 Camilla    555-2912  camilla.infusarum@skynet.be      R8 Fabius     555-1234  fabius.undevicesimus@ucb.edu     F9 Julie      555-6699  julie.perscrutabor@skeeve.com    F
10 Martin     555-6480  martin.codicibus@hotmail.com     A
11 Samuel     555-3430  samuel.lanceolis@shu.edu         A
12 Jean-Paul  555-2127  jeanpaul.campanorum@nyu.edu      R

// 这里没有 pattern, 空的, empty pattern, 那么就表示匹配输入记录永远成功, 也就是说永远为真, 这是龟腚. action永远都会执行.

我们知道, awk 的rule 就是由一系列 pattern 和 action 构成, 这里所谓的空 pattern, 也可以说是省略了 pattern, 那么 action 可不可以省略呢?
事实上, action也是可以省略的, 但如果省略了的话,它就会有一个默认的action行为, 即 { print $0 } !
很多人新手经常搞不懂一下的代码:

awk '{a=1}1' myfile

经常会碰到有人问, 这个代码后面的1是干嘛的? 其实, 我们拆分下 awk 的 rule 就明白了.
awk '{a=1}1' 这个语句包含了两条规则:

awk '
        [空pattern] {a=1}    #第一条规则
        1 [{省略的action}]   #第二条规则
'

第一条rule: {a=1} , 这条规则这里有一个{}大括号包裹着, 表示这是一个 action, 但是省略了pattern, 即空pattern, 
上面说了, 空pattern是永远匹配为真的, 
所以{a=1}这个action会针对每条输入记录对执行,只是我们看不到它的具体表现而已.

第二条rule: 1, 这条规则仅仅只有一个1字, 没有被{}大括号包裹着, 
所以这个1是一个pattern, 省略了{action}, 而这个数字 1 , 实际上就是一个常量表达式pattern, 因它为非0的数字,所以pattern匹配成功,为真,就执行action,
因为这里省略了{action},就触发默认的行为,而默认的action行为是print $0,即打印这条记录.

再如: awk '1;1' ,省略了两个action, 所以这条实际上就是两个 {print $0}{print $0}.

所以, 凡是action只是要输出这条记录的, 通通都可以省略这个 action.

如:

1 $ awk '/Amelia/ || /Martin/'  myfile
2 Amelia     555-5553  amelia.zodiacusque@gmail.com     F
3 Martin     555-6480  martin.codicibus@hotmail.com     A
4 $ awk '$NF ~ /F/'  myfile
5 Amelia     555-5553  amelia.zodiacusque@gmail.com     F
6 Fabius     555-1234  fabius.undevicesimus@ucb.edu     F
7 Julie      555-6699  julie.perscrutabor@skeeve.com    F
8 $ awk 'NR==5'  myfile
9 Broderick  555-0542  broderick.aliquotiens@yahoo.com  R

五. 特殊的 pattern: BEGIN, END ..

在 awk 中, 肯定会经常看到 BEGIN, END 这两个玩意儿. 如 awk 'BEGIN { ... } END { ... } '

实际上, BEGIN 和 END 只是两个特殊的 pattern . 类似的还有 BEGINFILE,  ENDFILE.

BEGIN 在读入文件之前匹配成功, 即为在读入文件之前这条 rule 就已经执行了.
END 在处理完文件之后才匹配陈宫, 即在处理完文件之后才会执行这条 rule.

1 $ awk 'BEGIN { n=5 } NR==n { print $0 } END { print $0 }' myfile
2 Broderick  555-0542  broderick.aliquotiens@yahoo.com  R
3 Jean-Paul  555-2127  jeanpaul.campanorum@nyu.edu      R

分析下这条 awk 语句:
首先, 它包含三条规则
1. BEGIN { n=5 }  ,BEGIN 为 特殊pattern, {n=5} 为 action
2. NR==n { print $0 }, NR==n 是一个比较表达式pattern, { print $0 } 为action.
3. END { print $0 }, END 也是一个特殊的pattern.

BEGIN 模式一般读入文件之前常用的是做一些相关的定义操作, 这里设定变量n=5. 
然后awk开始处理记录, 当 NR==n 时, 即处理到我们定义的那条记录时(第5条记录时), 执行 print $0, 输出这条记录.
最后是END模式, awk处理完文件里, END模式匹配成功,执行print $0, 即输出最后一条记录.
所以, 结果是输出第5条记录和最后一条记录.

六. 模式范围: begpat, endpat

这个模式范围, 是由两个 pattern 组成, 每个 pattern可以是任意的非特殊类型(非BEGIN/END模式类型)的pattern类型(可以是正则,比较,常量等pattern).
这个模式范围匹配的规则有点儿特殊, 这里以一个"开闸放水"的例子做为一个类比.
1. 首先以第一个pattern匹配输入记录, 如果第一个pattern匹配成功,就"打开放水的开关开始放水",[开关的状态: 开], 即会立即执行后面的action.此时不管第二个pattern是否匹配.
2. 接着再匹配第二pattern, 如果第二pattern匹配失败,开关的状态不变,即还是会执行action.
3. 接着继续以第二个pattern匹配下一条输入记录,直到第二个pattern匹配成功. 就"关闭放水的开关停止放水",[开关的状态: 关], 模式范围匹配结束.
4. 以1,2,3步骤进入下一轮模式范围匹配

如:

1 $ awk 'NR==4, /555-3430/ { print $0}' myfile
2 Bill       555-1675  bill.drowning@hotmail.com        A
3 Broderick  555-0542  broderick.aliquotiens@yahoo.com  R
4 Camilla    555-2912  camilla.infusarum@skynet.be      R
5 Fabius     555-1234  fabius.undevicesimus@ucb.edu     F
6 Julie      555-6699  julie.perscrutabor@skeeve.com    F
7 Martin     555-6480  martin.codicibus@hotmail.com     A
8 Samuel     555-3430  samuel.lanceolis@shu.edu         A

先执行 NR==4 这个 pattern 匹配, 当第四条记录匹配成功时, 放水开关打开, 开始放水了, 即开始执行action , 执行 print $0 , 输出第四条记录.
接着使用 /555-3430/ 当前记录, 不成功.
第5条记录继续执行 action.继续以第二个pattern匹配这条记录..不成功..,开关是开的
第6条记录继续执行 action.继续以第二个pattern匹配这条记录..不成功..,开关是开的
...
..
直到匹配 /555-3430/, 第二个pattern匹配成功. 开关关闭. 模式范围匹配结束..
开始下一轮模式范围匹配..

以上就是各种 pattern 的简要解说了.. 至于 action, 也没啥可说的, action一般做具体的事情.
那些个流程控制语句 if/for/while 等一般都属于action了, 不能做为 pattern了.

转载于:https://www.cnblogs.com/alplf123/p/9271910.html

(转)关于 awk 的 pattern(模式)相关推荐

  1. Java - 正则表达式的运用(Pattern模式和Matcher匹配)

    一.绪论: 在写程序的过程中,有时会需要匹配.查找.替换或者是判断字符串的出现情况,而且有时不能用简单的纯编码方式解决这些问题,这个时候就会想到要正则表达式,无论是Java, PHH, C#,  Py ...

  2. Linux三剑客和正则表达式的应用

    bash是什么 bash是一个命令处理器,运行在文本窗口中,并能执行用户直接的命令 bash还能从文件中读取Linux命令,称之为脚本 bash支持通配符.管道.命令替换.条件判断等逻辑控制语句 ba ...

  3. awk 6.0 — awk模式之二

    awk的语法 awk [options] 'Pattern {Actions}' file1,file2- 之前介绍了三种模式:空模式,关系运算模式,BEGIN/END模式 正则模式 模式可以理解成条 ...

  4. awk5.0 — awk模式之一

    再次重申awk的语法 awk [options] 'Pattern {Actions}' file1,file2- awk模式,在之前的文章中简单使用了BEGIN和END.这里的模式,其实我们可以理解 ...

  5. linux 重复模式元字符,Linux 正则表达式 vi, grep, sed, awk

    \> 锚定单词的结束,如'grep\>'匹配包含以grep结尾的单词的行. x\{m\} 重复字符x,m次,如:'o\{5\}'匹配包含5个o的行. x\{m,\} 重复字符x,至少m次, ...

  6. 【shell】shell脚本实战-awk工作模式讲解

    文章目录 awk工作的三个步骤 awk中的各种模式详解 1. awk 脚本拥有的形式 2. 正则表达式 3. 关系表达式 4. 组合的Pattern(模式) 5. Pattern1,Pattern2 ...

  7. 1. awk基础,awk介绍,awk基本语法,直接使用action,打印列,初识列和行,\$0、\$NF、NF,基础示例,begin模式,end模式

    文章目录 前言 awk介绍 awk基本语法 直接使用action 打印列 初识列和行 \$0.\$NF.NF 基础示例 初识模式(begin end) 总结 友情链接 前言 本小节是awk基础入门课程 ...

  8. awk - 模式扫描与处理语言

    awk - 模式扫描与处理语言 (第二版) Alfred V. Aho Brian W. Kernighan Peter J. Weinberger Bell Laboratories Murray ...

  9. 【ABAP】模式(Pattern)创建与使用

    一.模式的创建 在ABAP编辑界面按照如下的路径创建模式. 在弹出框中输入模式名. 即可进入模式编辑页面,按照自身的编码规则进行模式编辑,最后保存. Tip: 模式的最大限度为100行. 二.模式的使 ...

  10. C#LeetCode刷题之#290-单词模式(Word Pattern)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3778 访问. 给定一种 pattern(模式) 和一个字符串 s ...

最新文章

  1. mysql创建数据库选择_mysql创建、选择并使用数据库
  2. Docker容器相关命令
  3. key可以重复的map集合:IdentityHashMap
  4. .Net Core 环境安装
  5. 左耳朵耗子论微服务 Serverless 及 FaaS | GIAC 访谈
  6. Vue-Router API参考
  7. UI设计|搭配色彩素材专辑,轻松掌握要点
  8. JavaScript OO不XX 学习总结
  9. log4j 日志级别_log4j-Mybatis(5)
  10. JavaWeb — session+实战项目
  11. keyup常用事件_KeyUp 事件
  12. DVB机顶盒工作原理
  13. Hi3519AV100开发记录
  14. 神经网络中常用的误差平方和损失函数是什么
  15. 2019/5/第二周
  16. STM32 IO口模拟ISO7816(PSAM卡)协议
  17. 从零双排java之打印流
  18. Java中的正无穷,负无穷和非数
  19. 【c++】string模拟实现(三大基本成员函数)
  20. 二进制里的「逢二进一」是什么意思

热门文章

  1. 数组元素交换位置(奇数号元素在前,偶数号元素在后)
  2. JavaOOP定义并测试宠物类
  3. 天载优配概述电力掀起涨停潮
  4. 一篇文章带你搞定 MongoDB 中的管道操作符($group、$unwind、$sort、$limit、$skip)
  5. Azuri将太阳能发电引入非洲,想做的是将更多人纳入“共享经济”
  6. vue的分页打印功能
  7. 浙江师范计算机考研,【计算机考研】院校信息-浙江师范大学
  8. 【实验报告】实验四、彩色图像处理
  9. 记一次内存溢出排查过程
  10. MA-Net:用于肝脏和肿瘤分割的多尺度注意力网络