《Linux命令行与shell脚本编程大全》第二十章 正则表达式
20.1 什么是正则表达式
20.1.1 定义
正则表达式是你所定义的模式模板。linux工具可以用它来过滤文本。
正则表达式利用通配符来描述数据流中第一个或多个字符。
正则表达式模式含有文本或特殊字符,为sed编辑器和gawk程序定义了一个匹配数据时采用的模板。
20.1.2 正则表达式的类型
使用正则表达式最大的问题在于有不止一种类型的正则表达式。
正则表达式是通过正则表达式引擎实现的,正则表达式引擎是一套底层软件,负责解释正则表达式模式并使用这些模式进行文本匹配。
在linux中有两种流行的正则表达式引擎:
1)POSIX基础正则表达式(BRE)引擎
2)POSIX扩展正则表达式(ERE)引擎
大部分linux工具都至少符合POSIX BRE引擎规范,能够识别该规范定义的所有模式符号。
但是,有些工具只支持BRE引擎规范下的子集。比如sed,这是出于速度方面的考虑。
gawk程序用ERE引擎来处理它的正则表达式模式。
20.2 定义BRE模式
20.2.1 纯文本
例子:
$echo “This is test line” | sed -n ‘/test/p’
$echo “This is test line” | gawk ‘/test/{print $0}’
正则表达式并不关心模式在数据流中的位置,也不关心出现了多少次,只要匹配了就会将该字符串传会linux工具。
正则表达式模式区分大小写。
20.2.2 特殊字符
正则表达式识别的特殊字符包括:
.*[]^${}\+?|()
如果要用某个特殊字符作为文本字符,就必须转义。在前面加上反斜线\。
比如:
$echo “This cost is \$200” | sed –n ‘/\$/p’ // 注意这里应该是\$200,而不是$200
$echo “\ hahah, this is fanxiexian” | sed –n ‘/\\/p’
要使用正斜线也需要用转义字符
$ehco “6 / 3 = 2” | sed -n ‘/\//p’
20.2.3 锚字符 ^ $
默认情况下,模式出现再数据流中的任何地方,它就能匹配。
有两个特殊字符可以用来将模式锁定在数据流中的行首或行尾。
1.锁定在行首(脱字符 ^)
^ 定义从数据流中文本行的行首开始的模式。如果模式出现在行首之外的位置,正则表达式模式则无法匹配。
需要用^,就必须将它放在正则表达式中指定的模式前面。
比如:
$echo “The book store” | sed –n ‘/^book/p’ // 这样不会有输出
$echo “The book store” | sed –n ‘/^The/p’ // 这个才有
还可以输入文件:
$sed -n ‘/^this/p’ data.txt
data.txt 中以this开头的行就能找出来。
注意如果将^放到模式开头之外的其他位置,那么久跟普通字符一样了。
$echo “This is ^ test” | sed –n ‘/is ^/p’ // 匹配 is ^ 。
注意:
如果指定正则表达式模式时只用了脱字符,就不需要用反斜线来转义。
如果你在模式中先指定了脱字符,随后还有一些其他文本,那么你必须在脱字符前用转义字符。
2. 锁定在行尾
用美元符$
$echo “This is test line” | sed –n ‘/line$/p’ //这样可以匹配到
$echo “This is test lines” | sed –n ‘/line$/p’ //这样不可以匹配到
要想匹配,文本模式必须是行的最后一部分。
3. 组合锚点
比如想到匹配指定内容
$sed ‘/^this is test line$/p’ data.txt // 匹配行 this is test line
将两个锚点直接组合在一起,之间不加任何东西,这样就过滤出数据流中的空白行。
$sed -n ‘/^$/p’ data.txt // 这样可以把data.txt 中的空白行过滤出来。
20.2.4 点号字符 .
用来匹配除换行符之外的任意单个字符。它必须匹配一个字符,如果点字符的位置没有字符那么模式就不成立。
例子:
xcy@xcy-virtual-machine:~/shell/20zhang$ cat data.txt
this is a test line
the cat is sleeping
that is a very nice hat
this test is at line four
at ten o'clock we'll go home
xcy@xcy-virtual-machine:~/shell/20zhang$ sed -n '/.at/p' data.txt
the cat is sleeping
that is a very nice hat
this test is at line four
xcy@xcy-virtual-machine:~/shell/20zhang$
空格也算一个字符。注意第5行没有匹配到。at前面没有字符了。
20.2.5 字符组 []
可以限定待匹配的具体字符,在正则表达式中,这称为字符组。用[]括起来
比如:
$sed –n ‘/[ch]at/p’ data.txt // 相当于只匹配cat 或者 hat。其他的at就不匹配了。
在不确定大小写的时候,字符组会非常有用:
$echo “Yes” | sed –n ‘/[yY]es/p’
还可以用多个字符组:
$echo ‘YeS’ | sed –n ‘/[Yy][Ee][Ss]/p’
这样就相当于可以限制行的字符个数和区间了
20.2.6 排除型字符组
相当于字符组取反,可以寻找字符组中没有的字符。在前面加个脱字符就好了。
$sed –n ‘/[^ch]at/p’ data.txt
匹配出c和h以外的字符。
20.2.7 区间
0 – 9,可以直接这么写[0-9] 而不需要[0123456789]
$sed –n ‘/^[0-9][0-9][0-9][0-9]&/p’ data.txt
字母也可以
$sed –n ‘/[c-h]at/p’ data.txt // 匹配c到h这个区间的字符。
还可以指定多个不连续的区间:
$sed –n ‘/[a-ch-m]at/p’ data.txt // 指定 a-c 和 h-m区间的字母。
$echo “This is foot” | sed –n ‘/[a-ch-n]oot/p’
20.2.8 特殊的字符组
除了自定义的区间(比如[0-9] [a-f])之外,BRE还包含了一些特殊的字符组。见下表
|
组 |
描述 |
|
[[:alpha:]] |
匹配任意字母字符,不管大小写 |
|
[[:alnum:]] |
匹配任意字母数字字符 0-9 a-z A-Z |
|
[[:blank:]] |
匹配空格或制表符 |
|
[[:digit:]] |
匹配数字 0-9 |
|
[[:lower:]] |
匹配小写字母 a-z |
|
[[:print:]] |
匹配任意可打印字符 |
|
[[:punct:]] |
匹配标点符号 |
|
[[:space:]] |
匹配任意空白字符:空格、制表符、NL、FF、VT和CR |
|
[[:upper:]] |
匹配大写字母A-Z |
使用:
$echo “achsdsd” | sed –n ‘/[[:digit:]]/p’
$echo “2344” | sed –n ‘/[[:digit:]]/p’
$echo “achsdsd” | sed –n ‘/[[:lower:]]/p’
$echo “this is , a test” | sed –n ‘/[[:punct:]]/p’
20.2.9 星号 *
在字符后面放置星号用来表明该字符必须在匹配模式的文本中出现0次或多次。
例子:
$echo “I am hahahaaaaa” | sed -n ‘/ha*h/p’ // 表明a可以出现0次或多次。
*还能用到字符组上,它允许指定可能在文本中出现多次的字符组或区间:
$echo ‘bt’ | sed –n ‘/b[ae]*t/p’ // a出现0次或次,e出现0次或多次
20.3 扩展正则表达式(POSIX ERE)
提供了一些可以供linux应用和工具使用的额外符号。
gawk程序(会慢一点)能够识别,sed编辑器(查找比较快)不能识别。
20.3.1 问号?
类似于星号,但是有点不同。
问号表明前面的字符可以出现0次或1次,不会匹配出现多次的字符。
$echo “bt” | gawk ‘/be?t/{print $0}’
$echo “bet” | gawk ‘/be?t/{print $0}’
$echo “beet” | gawk ‘/be?t/{print $0}’ // e 出现了2次,这里就不输出了
还可以跟字符组一起使用:
$echo “bet” | gawk ‘/b[ae]?t/{print $0}’
$echo “bat” | gawk ‘/b[ae]?t/{print $0}’
$echo “baet” | gawk ‘/b[ae]?t/{print $0}’ // 这里相当于出现了2次,也不会输出
$echo “baet” | gawk ‘/b[a-f]?t/{print $0}’
20.3.2 加号+
有点像*号。但是必须出现1次以上。可以有多次
$echo “baet” | gawk ‘/b[ae]+t/{print $0}’
20.3.3 使用花括号{}
花括号允许你为可重复的正则表达式指定一个上限,这通常称为间隔。可以用两种格式来指定区间。
1)m:正则表达式准确出现m次
2)m,n:正则表达式至少出现m次,至多n次。
注意:默认情况下gawk程序不识别正则表达式间隔。必须指定gawk程序的 –re-interval命令行选项才能识别正则表达式间隔。
例子:
$echo “bt” | gawk –re-interval ‘/be{1}t/{print $0}’ // 指定出现1次e
$echo “bet” | gawk –re-interval ‘/be{1}t/{print $0}’
$echo “beeet” | gawk –re-interval ‘/be{3,6}t/{print $0}’ // e至少出现3次,至多6次
$echo “baaeeet” | gawk –re-interval ‘/b[ae]{1,3}t/{print $0}’ // a e 出现1 -3 次
20.3.4 管道符号|
管道符号允许你在检查数据流时,用逻辑or方式指定正则表达式引擎要用的两个或多个模式。
格式如下:
expr1|expr2|……
例子:
echo "the dog is sleeping" | gawk '/cat|dog/{print $0}' // 去匹配cat或dog
echo "the tat is sleeping" | gawk '/[ct]at|dog/{print $0}' // 去匹配 [ct]at或dog
20.3.5 表达式分组()
正则表达式模式也可以用圆括号进行分组。当你将正则表达式模式分组时,该组会被视为一个标准字符。可以像对普通字符一样给该组使用特殊字符。
例子:
$echo “Sat” | gawk ‘/Sat(urday)?/ {print $0}’
相当于把urday当做一个整体了, /SatF?/ 跟这个类似,F出现0次或1次。
()需要转义的用法:
echo "Sat(urday)" | gawk '/Sat\(urday\)/ {print $0}'
echo "Saturday" | gawk '/Sat\(urday\)/ {print $0}'
还可以将分组和管道符号一起使用来创建可能的模式匹配组:
echo "cat" | gawk '/(b|c)a(b|t)/ {print $0}'
这样相当于匹配 bab bat cab cat 四种。
20.4 正则表达式实战
20.4.1 目录文件计数
这个例子用于对PATH环境变量中各个目录里的可执行文件进行计数:
#!/bin/bash
mypath=$(echo $PATH | sed 's/:/ /g') # 这里把用冒号分割的字符串换成用空格分割
#echo "mypath = $mypath"
count=0
for dir in $mypath
do
check=$(ls $dir) // 查询单个目录
for item in $check
do
count=$[ count + 1 ]
done
echo "$dir - $count"
count=0
done
20.4.2 验证电话号码
美国的号码格式如下:
(223)456-7890
(223) 456-7890
223-456-7890
223.456.7890
最开始是( : ^\(?
三位区号(第一位必须大于2):[2-9][0-9]{2}
然后又是括号:\)?
然后是分隔符(空格,点,减号):( |-|\.)
然后是3位数字:[0-9]{3}
又是分隔符:( |-|\.)
最后四位数字:[0-9]{4}
连起来就是:
^\(?[2-9][0-9]{2}\)?( |-|\.)[0-9]{3}( |-|\.)[0-9]{4}$
例子:
xcy@xcy-virtual-machine:~/shell/20zhang$ cat isphone
#!/bin/bash
gawk --re-interval '/^\(?[2-9][0-9]{2}\)?( |-|\.)[0-9]{3}( |-|\.)[0-9]{4}$/ {print $0}'
xcy@xcy-virtual-machine:~/shell/20zhang$ echo "222-098-2231" | ./isphone
222-098-2231
xcy@xcy-virtual-machine:~/shell/20zhang$ echo "122-098-2231" | ./isphone
xcy@xcy-virtual-machine:~/shell/20zhang$ echo "222.098.2231" | ./isphone
222.098.2231
xcy@xcy-virtual-machine:~/shell/20zhang$
还可以将整个文件重定向到脚本:
phonelist里面存放着一行一行的数据:
$cat phonelist | ./isphone
这个例子其实也不是特别合理,比如下面几种情况也算是合法号码:
(235.561-4430
343) 451.4651
总之还是有待优化。
20.4.3 解析邮件地址
邮件地址的形式如下:
username@hostname
username值可用字母数字字符以及以下特殊字符:
1)点号
2)单破折线
3)加号
4)下划线
hostname部分由一个或多个域名和一个服务器名组成。只允许字母数字字符以及下面的特殊字符:比如(xiaochongyong@amwell-haha.com)
1)点号
2)下划线
username@相当于:^([a-zA-Z0-9_\-\.\+]+)@
注意: [] 里面是字符组,相当于之前的[xcs]。() 里面是表达式分组
hostname相当于:([a-zA-Z0-9_\-\.\]+)
后面还要接顶级域名。.com .cn .org 等
只能是字母字符,必须不少于两个字符,长度不超多5个字符:\.([a-zA-Z]{2,5})$
连起来就是:
^([a-zA-Z0-9_\.\-\+]+)@([a-zA-Z0-9_\.\-]+)\.([a-zA-Z]{2,5})$
例子:
xcy@xcy-virtual-machine:~/shell/20zhang$ cat isemail
#!/bin/bash
gawk --re-interval '/^([a-zA-Z0-9_\.\-\+]+)\@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/ {print $0}'
xcy@xcy-virtual-machine:~/shell/20zhang$ echo "222x2iaochongyong@s1amwell-elec.com" | ./isemail
222x2iaochongyong@s1amwell-elec.com
xcy@xcy-virtual-machine:~/shell/20zhang$ echo "222x2iaocho%ngyong@s1amwell-elec.com" | ./isemail
xcy@xcy-virtual-machine:~/shell/20zhang$ echo "222x2iaocho%ngyong+@s1amwell-elec.com" | ./isemail
xcy@xcy-virtual-machine:~/shell/20zhang$ echo "222x2iaochongyong+@s1amwell-elec.com" | ./isemail
222x2iaochongyong+@s1amwell-elec.com
xcy@xcy-virtual-machine:~/shell/20zhang$ echo "222x2iaochongyong+@s1amwell-elec..com" | ./isemail
222x2iaochongyong+@s1amwell-elec..com
xcy@xcy-virtual-machine:~/shell/20zhang$ echo "222x2iaochongyong+@s1amwell-elec._.com" | ./isemail
222x2iaochongyong+@s1amwell-elec._.com
xcy@xcy-virtual-machine:~/shell/20zhang$
20.5 小结
正则表达式定义了用来过滤数据流中文本的模式模板。
模式由标准文本字符和特殊字符的组成。
正则表达式引擎用特殊字符来匹配一系列单个或多个字符,这类似于其他应用程序中通配符的工作方式。
《Linux命令行与shell脚本编程大全》第二十章 正则表达式的更多相关文章
- Linux命令行与shell脚本编程大全.第3版(文字版) 超清文字-非扫描版 [免积分、免登录]
此处免费下载,无需账号,无需登录,无需积分.收集自互联网,侵权通知删除. 点击下载:Linux命令行与shell脚本编程大全.第3版 (大小:约22M)
- 《Linux命令行与shell脚本编程大全 第3版》创建实用的脚本---11
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
- 《Linux命令行与shell脚本编程大全 第3版》高级Shell脚本编程---47
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
- 《Linux命令行与shell脚本编程大全 第3版》Shell脚本编程基础---57
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---57
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---56
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---55
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---54
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---53
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
- 《Linux命令行与shell脚本编程大全 第3版》Linux命令行---52
以下为阅读<Linux命令行与shell脚本编程大全 第3版>的读书笔记,为了方便记录,特地与书的内容保持同步,特意做成一节一次随笔,特记录如下:
随机推荐
- ASP.NET MVC 分页问题
在使用Ajax.Pager进行分页的时候需要注意一下几个方面: 1.一定要引入jquery.unobtrusive-ajax.min.js这个js: 2.一定要在页面中使用注册分页器,注册方法:@{H ...
- angular之scope详解
AngularJS的一些指令会创建子作用域,而子作用域会继承自父作用域,大致可分为以下3种 1.创建子作用域并继承父作用域的指令 ng-repeat ng-include ng-switch ng-c ...
- 集群配置虚拟主机及部署Hadoop集群碰到的问题
配置集群方案 Ubuntu下的配置apache虚拟主机方案: 对其中的Master节点配置虚拟主机,可以通过Chrome浏览器访问目录. 安装虚拟主机之前,先安装Apache2 sudo apt-ge ...
- no device found for connection ‘ System eth0′问题
我用的是centos6 在ping 百度的时候ping不通 提示错误no device found for connection ' System eth0′ 解决方法:虚拟机右上角有一个小电脑的标志 ...
- Hive中常用的查询命令
日志数据的统计处理在这里反倒没有什么特别之处,就是一些 SQL 语句而已,也没有什么高深的技巧,不过还是列举一些语句示例,以示 hive 处理数据的方便之处,并展示 hive 的一些用法. a) ...
- Grunt打包seajs项目
在使用seajs时,常常将若干脚本分为多次require进来,这样开发中比较方便,但是,会增加http请求次数,在生产环境中需要进行打包合并.压缩等操作. 以Grunt构建工具为例,对一个seajs项 ...
- Boolean 相关
Boolean(something) 会把里面的变量转化为布尔型 当我们用if(something)判断的时候,相当于调用了这个函数 转化规则如下 DATA TYPE VALUES CONVE ...
- CodeForces - 706B 二分stl
#include<iostream> #include<cstdio> #include<cstring> #include<string> #incl ...
- Ubuntu 共享 转载
Ubuntu 14.04 文件服务器--samba的安装和配置 听语音 | 浏览:29526 | 更新:2014-10-10 22:28 | 标签:ubuntu 1 2 3 4 5 6 7 分步阅读 ...
- Node.js CVE-2017-1484复现(详细步骤)
0x00 前言 早上看Sec-news安全文摘的时候,发现腾讯安全应急响应中心发表了一篇文章,Node.js CVE-2017-14849 漏洞分析(https://security.tencent. ...