(转)关于 awk 的 pattern(模式)
本文转自chinaunix http://bbs.chinaunix.net/thread-4246512-1-1.html 作者reyleon
我们知道, awk程序由一系列 pattern 以及与之对应的 action 组成的 rule 组成,rule之间用";"分号隔开, 一条输入记录与 pattern 匹配则执行与之关联的action, 如下所示:
awk '
pattern { action };
pattern { action };
.....
'
可是, 很多人并不清楚什么东西可以做为 pattern下面就来聊聊这些个事儿. 以下文本做为测试文本:
$ cat myfile
Amelia - amelia.zodiacusque@gmail.com F
Anthony - anthony.asserturo@hotmail.com A
Becky - becky.algebrarum@gmail.com A
Bill - bill.drowning@hotmail.com A
Broderick - broderick.aliquotiens@yahoo.com R
Camilla - camilla.infusarum@skynet.be R
Fabius - fabius.undevicesimus@ucb.edu F
Julie - julie.perscrutabor@skeeve.com F
Martin - martin.codicibus@hotmail.com A
Samuel - samuel.lanceolis@shu.edu A
Jean-Paul - jeanpaul.campanorum@nyu.edu R
首先, 要记住, 凡是被 {} 包裹的, 就是 action, 或者说, action 必然被 {} 包裹着
凡是没有被{}包裹的, 就是pattern, 或者说pattern不能被{}包裹着.
一. 正则表达式做为 pattern
最常见的, 就是一个正则表达式做为一个 pattern了, 如:
awk '/555-5553/ { print $0 }' myfile
/555-5553/ 就是一个正则表达式, 如果输入记录匹配555-5553, 就输出这条记录, 这里只有第一行匹配 555-5553, 所以就输出了第一行这条记录.
$ awk '/555-5553/ { print $0 }' myfile
Amelia - amelia.zodiacusque@gmail.com F
二. 比较表达式做为 pattern
$ awk '$NF == "A" { print $0 }' myfile
Anthony - anthony.asserturo@hotmail.com A
Becky - becky.algebrarum@gmail.com A
Bill - bill.drowning@hotmail.com A
Martin - martin.codicibus@hotmail.com A
最后一个字段为 "A" 的, 输出这条记录.
$ awk '$NF != "A" { print $0 }' myfile
Amelia - amelia.zodiacusque@gmail.com F
Broderick - broderick.aliquotiens@yahoo.com R
Camilla - camilla.infusarum@skynet.be R
Fabius - fabius.undevicesimus@ucb.edu F
Julie - julie.perscrutabor@skeeve.com F
Jean-Paul - jeanpaul.campanorum@nyu.edu R
最后一个字段不为 "A" 的, 输出这条记录.
三. 常量表达式做为 pattern
这种pattern一般是最不易被新手理解的, 事实上, 既然是 pattern 匹配, 结果就只有两种情况, 要么匹配(即为真),就执行后面的 action, 要么不匹配(即为假), 就不会执行后面的action.
所以, awk 的规则基本上也就是:
awk ' 真 { 执行代码 }; 假 { 不执行代码 }'
也理解为:
awk ' 条件 { 动作 } 条件 { 动作 } '
什么东西可以做为一个常量? 一个数字, 或者一个字符串, 都可以做为一个常量 pattern. 那这里就有一个龟腚了:
凡是非0的数字, 就表示pattern匹配成功, 也就是pattern为真. 否则表示匹配失败, 为假.
凡是非空的字符串, 就表示pattern匹配成功, 也就是pattern为真. 否则表示匹配失败, 为假.
注意: 字符串是由引号引起来的! 比如数字 0 与 字符串 "0" 不是一样的. 数字0为假, 字符串"0"为真(不为空).
如:
$ awk '1 { print $0 }' myfile
Amelia - amelia.zodiacusque@gmail.com F
Anthony - anthony.asserturo@hotmail.com A
Becky - becky.algebrarum@gmail.com A
Bill - bill.drowning@hotmail.com A
Broderick - broderick.aliquotiens@yahoo.com R
Camilla - camilla.infusarum@skynet.be R
Fabius - fabius.undevicesimus@ucb.edu F
Julie - julie.perscrutabor@skeeve.com F
Martin - martin.codicibus@hotmail.com A
Samuel - samuel.lanceolis@shu.edu A
Jean-Paul - jeanpaul.campanorum@nyu.edu R
$ awk '2 { print $0 }' myfile
Amelia - amelia.zodiacusque@gmail.com F
Anthony - anthony.asserturo@hotmail.com A
Becky - becky.algebrarum@gmail.com A
Bill - bill.drowning@hotmail.com A
Broderick - broderick.aliquotiens@yahoo.com R
Camilla - camilla.infusarum@skynet.be R
Fabius - fabius.undevicesimus@ucb.edu F
Julie - julie.perscrutabor@skeeve.com F
Martin - martin.codicibus@hotmail.com A
Samuel - samuel.lanceolis@shu.edu A
Jean-Paul - jeanpaul.campanorum@nyu.edu R
$ awk '0 { print $0 }' myfile
// 数字 0 做为 pattern, 0为假, pattern 匹配失败, 所以不执行 print $0, 没有打印.
$ awk ' "0" { print $0 }' myfile
Amelia - amelia.zodiacusque@gmail.com F
Anthony - anthony.asserturo@hotmail.com A
Becky - becky.algebrarum@gmail.com A
Bill - bill.drowning@hotmail.com A
Broderick - broderick.aliquotiens@yahoo.com R
Camilla - camilla.infusarum@skynet.be R
Fabius - fabius.undevicesimus@ucb.edu F
Julie - julie.perscrutabor@skeeve.com F
Martin - martin.codicibus@hotmail.com A
Samuel - samuel.lanceolis@shu.edu A
Jean-Paul - jeanpaul.campanorum@nyu.edu R
// 字符串 "0" 做为 pattern, 为真, pattern 匹配成功, 所以执行 print $0, 打印.
还有一些, 可能是写错的赋值语句做为了pattern的, 或者其他乱七八糟的, 等等..:
$ awk 'a=0' myfile // 数字0. 假, 没输出.
$ awk 'a=1' myfile // 1 为真.
Amelia - amelia.zodiacusque@gmail.com F
Anthony - anthony.asserturo@hotmail.com A
Becky - becky.algebrarum@gmail.com A
Bill - bill.drowning@hotmail.com A
Broderick - broderick.aliquotiens@yahoo.com R
Camilla - camilla.infusarum@skynet.be R
Fabius - fabius.undevicesimus@ucb.edu F
Julie - julie.perscrutabor@skeeve.com F
Martin - martin.codicibus@hotmail.com A
Samuel - samuel.lanceolis@shu.edu A
Jean-Paul - jeanpaul.campanorum@nyu.edu R
$ awk 'x-1' myfile // x 为未定义的变量, 做数学运算, 结果为 -1 , 因 -1 也是非0的数字常量, pattern 匹配成功, 为真, print $0.
Amelia - amelia.zodiacusque@gmail.com F
Anthony - anthony.asserturo@hotmail.com A
Becky - becky.algebrarum@gmail.com A
Bill - bill.drowning@hotmail.com A
Broderick - broderick.aliquotiens@yahoo.com R
Camilla - camilla.infusarum@skynet.be R
Fabius - fabius.undevicesimus@ucb.edu F
Julie - julie.perscrutabor@skeeve.com F
Martin - martin.codicibus@hotmail.com A
Samuel - samuel.lanceolis@shu.edu A
Jean-Paul - jeanpaul.campanorum@nyu.edu R
$ awk 'xxoo' myfile //xxoo为变量, 未赋值, 为假
$ awk '"xxoo"' myfile // 字符串, 真.
Amelia - amelia.zodiacusque@gmail.com F
Anthony - anthony.asserturo@hotmail.com A
Becky - becky.algebrarum@gmail.com A
Bill - bill.drowning@hotmail.com A
Broderick - broderick.aliquotiens@yahoo.com R
Camilla - camilla.infusarum@skynet.be R
Fabius - fabius.undevicesimus@ucb.edu F
Julie - julie.perscrutabor@skeeve.com F
Martin - martin.codicibus@hotmail.com A
Samuel - samuel.lanceolis@shu.edu A
Jean-Paul - jeanpaul.campanorum@nyu.edu R
四. 空 pattern
$ awk '{print $0}' myfile
Amelia - amelia.zodiacusque@gmail.com F
Anthony - anthony.asserturo@hotmail.com A
Becky - becky.algebrarum@gmail.com A
Bill - bill.drowning@hotmail.com A
Broderick - broderick.aliquotiens@yahoo.com R
Camilla - camilla.infusarum@skynet.be R
Fabius - fabius.undevicesimus@ucb.edu F
Julie - julie.perscrutabor@skeeve.com F
Martin - martin.codicibus@hotmail.com A
Samuel - samuel.lanceolis@shu.edu A
Jean-Paul - 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.
如:
$ awk '/Amelia/ || /Martin/' myfile
Amelia - amelia.zodiacusque@gmail.com F
Martin - martin.codicibus@hotmail.com A
$ awk '$NF ~ /F/' myfile
Amelia - amelia.zodiacusque@gmail.com F
Fabius - fabius.undevicesimus@ucb.edu F
Julie - julie.perscrutabor@skeeve.com F
$ awk 'NR==5' myfile
Broderick - broderick.aliquotiens@yahoo.com R
五. 特殊的 pattern: BEGIN, END ..
在 awk 中, 肯定会经常看到 BEGIN, END 这两个玩意儿. 如 awk 'BEGIN { ... } END { ... } '
实际上, BEGIN 和 END 只是两个特殊的 pattern . 类似的还有 BEGINFILE, ENDFILE.
BEGIN 在读入文件之前匹配成功, 即为在读入文件之前这条 rule 就已经执行了.
END 在处理完文件之后才匹配陈宫, 即在处理完文件之后才会执行这条 rule.
$ awk 'BEGIN { n=5 } NR==n { print $0 } END { print $0 }' myfile
Broderick - broderick.aliquotiens@yahoo.com R
Jean-Paul - 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步骤进入下一轮模式范围匹配
如:
$ awk 'NR==4, /555-3430/ { print $0}' myfile
Bill - bill.drowning@hotmail.com A
Broderick - broderick.aliquotiens@yahoo.com R
Camilla - camilla.infusarum@skynet.be R
Fabius - fabius.undevicesimus@ucb.edu F
Julie - julie.perscrutabor@skeeve.com F
Martin - martin.codicibus@hotmail.com A
Samuel - 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了.
(转)关于 awk 的 pattern(模式)的更多相关文章
- awk 的 pattern(模式)
我们知道, awk程序由一系列 pattern 以及与之对应的 action 组成的 rule 组成,rule之间用";"分号隔开, 一条输入记录与 pattern 匹配则执行与之 ...
- 关于awk的范围模式功能问题
关于awk的范围模式功能问题 man awk中这样写到 The pattern1, pattern2 form of an expression is called a range pattern. ...
- 多线程程序设计学习(3)immutable pattern模式
Immutable pattern[坚不可摧模式] 一:immutable pattern的参与者--->immutable(不变的)参与者 1.1:immutable参与者是一个 ...
- 多线程程序设计学习(9)worker pattern模式
Worker pattern[工作模式]一:Worker pattern的参与者--->Client(委托人线程)--->Channel(通道,里边有,存放请求的队列)--->Req ...
- 290.单词模式。给定一种 pattern(模式) 和一个字符串 str ,判断 str 是否遵循相同的模式。(c++方法)
题目描述: 给定一种 pattern(模式) 和一个字符串 str ,判断 str 是否遵循相同的模式. 这里的遵循指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之 ...
- 给定一种 pattern(模式) 和一个字符串 str ,判断 str 是否遵循相同的模式。 这里的遵循指完全匹配,例如, pattern 里的每个字母和字符串 str 中的每个非空单词之间存在着双向连接的对应模式。
这个是LeetCode上的一道题目.本机上运行时正确的,但是LeetCode上显示是错误的,所以没有办法了只能记录在博客上了. 我的想法是先把pattern和str都转化成数组.例如"abb ...
- awk模式pattern
awk模式pattern 再来回顾下awk的语法 awk [option] 'pattern[action]' file ... awk是按行处理文本,刚才讲解了print动作,现在讲解特殊的patt ...
- CU论坛常用知识点汇总
1.正则表达式详解 http://bbs.chinaunix.net/thread-63273-1-1.html http://bbs.chinaunix.net/thread-605570-1-1. ...
- awk(2)-模式(pattern)
在上文 awk(1)-简述我们将简要描述了awk的主要使用方向和构成(由一个或多个模式-动作组成),本小节主要讲述awk的各种模式. ps:例子中使用的输入文件(如countries)内容可由awk( ...
随机推荐
- dojo省份地市级联之省份Dao实现类(五)
dojo省份地市级联之省份Dao实现类 ProvinceDaoImpl.java: /** * */ package com.you.dao.impl; import java.util.ArrayL ...
- DOS批处理命令递归删除给定的文件(夹),兼VC工程清理小工具
使用dos批处理命令递归删除指定的文件(夹): (下面内容针对清理VC工程!自己按说明任意修改) 2014-06-10修改:删除前增加了[y,n]询问: echo off rem 递归删除当前文件下指 ...
- jenkins部署web项目到webogic
注: Docker容器里安装的jenkins,Docker容易里安装的weblogic 在jenkins里面直接将打包好的 war 包通过 Publish over SSH插件 放入 weblogic ...
- java实现全排列问题
1.问题描述: 一组字符串的全排列,按照全排列的顺序输出,并且每行结尾无空格. 2.输入: 输入一个字符串 3.输入示例: 请输入全排列的字符串: abc 4.输出示例: a b c a c b b ...
- freemarker中的left_pad和right_pad(十五)
freemarker中的left_pad和right_pad 1.简易说明 (1)left_pad 距左边 (2)right_pad 距右边 (3)当仅仅只有一个参数时,插入的是空白:当有两个参数时, ...
- JavaScript设计模式(9)-享元模式
享元模式 1. 介绍 一种优化模式 适合解决因创建大量类似对象而累积性能问题 javaScript 代码可能很快就用光浏览器的内容,通过把大量独立对象转化为少量共享对象,可以降低运行 Web 应用所需 ...
- C#隐式转换和显示转换举例--C#基础
高精度的数据类型转换为低精度的数据类型是显示转换,低精度的转换为高精度的是隐式转换. 温馨提示:不能说强制类型转换是从低精度到高精度. int a=666;float b=(float)a: 由a到b ...
- SpringMVC 注解式开发
SpringMVC的注解式开发是指,处理器是基于注解的类的开发.对于每一个定义的处理器,无需再配置文件中逐个注册,只需在代码中通过对类与方法的注解,便可完成注册.即注解替换是配置文件中对于处理器的注册 ...
- angularJs $mdDialog和$uibModal弹框关闭传值
$mdDialog以一个点击button按钮出现弹框为例: $scope.btn=function($event,row){ var dScope = $scope.$new(true); dScop ...
- Delphi关于TAdvStringGrid控件颜色的设置
FixedFont-Color 标题行和列字体的颜色 Font-color 单元格字体的颜色Visual-color 整个表格的背景色填充