20 正则表达式
20.1 什么是正则表达式
20.1.1 定义
使用模式字符串匹配文本,如果不匹配就被过滤。*
匹配任意多个字符。
20.1.2 正则表达式的类型
不同的工具使用不同的正则表达式引擎:
1.POSIX基础正则表达式(basic regular expression,BRE)引擎
2.POSIX扩展正则表达式(extended regular expression,ERE)引擎
20.2 定义BRE模式
20.2.1 纯文本
直接找到含有test的语句打印出来
$ echo "This is a test" | sed -n '/test/p'
This is a test
正则表达式严格区分大小写,例如由于是大写所以怎么都不能匹配
$ echo "This is a test" | sed -n '/Test/p'
20.2.2 特殊字符
正则表达式的特殊字符包括:.*[]^${}\+?|()
除了上面的特殊字符,还要小心:\
如果要使用上面这些字符,必须使用反斜线\
实现转义。例如:
$ echo "The cost is \$4.0" | sed -n "/\$/p"
The cost is $4.0
20.2.3 锚字符
当指定一个正则表达式模式时,只要模式出现在数据流中的任何地方,它就能匹配。有两个特殊字符可以用来将模式锁定在数据流中的行首或行尾。
1.锁定在行首
^
定义从数据流文本行行首开始的模式,只能放在模式开头,否则就是普通字符。
$ echo "This ^ is a test" | sed -n '/^T/p'
This ^ is a test
$ echo "This ^ is a test" | sed -n '/This ^/p'
This ^ is a test
2.锁定在行尾
$
定义从数据流文本行行首开始的模式,必须完全按照指定字符串匹配。
$ echo "This is a good book" | sed -n "/book$/p"
This is a good book
3.组合锚点
在一些常见情况下,可以在同一行中将行首锚点和行尾锚点组合在一起使用。
$ cat data4
this is a test of using both anchors
I said this is a test
this is a test
I'm sure this is a test.
$ sed -n '/^this is a test$/p' data4
this is a test
利用过滤空白行:sed '/^$/d' filename
20.2.4 点字符
.
匹配任意单个字符,但是必须匹配这个字符。
20.2.5 字符组
限制指定字符,使用[]
,内部应当包含希望出现的字符,必须匹配其中一个字符。
$ echo "Yes" | sed -n '/[Yy]es/p'
Yes
$ echo "Yes" | sed -n '/[abs]es/p'
$
使用字符组匹配5位数字的邮编
$ sed -n '/^[0123456789][0123456789][0123456789][0123456789][0123456789]$/p' data3.txt
60633
46201
22203
12983
20.2.6 排除型字符组
即[^]
括号内排除掉对应的字符,但仍然必须匹配一个字符
20.2.7 区间
可以通过指定区间匹配区间内的字符
$ sed -n '/^[0-9][0-9][0-9][0-9][0-9]$/p' data3.txt
60633
46201
22203
12983
20.2.8 特殊的字符组
特殊的字符组表:
使用字符组
echo "abc" | sed -n '/[[:alpha:]]/p'
abc
20.2.9 星号
星号表明该字符必须在匹配模式的文本中出现0次或多次,经常与字符组或者.
结合使用。
$ echo "ieeeek" | sed -n '/ie*k/p'
20.3 扩展正则表达式
20.3.1 问号
问号表明前面的字符可以出现0次或1次,但只限于
此。
$ echo "bt" | gawk '/be?t/{print $0}'
bt
echo "bat" | gawk '/b[ae]?t/{print $0}'
bat
20.3.2 加号
加号表明前面的字符可以出现1次或多次,但必须至少出现1次。
$ echo "beeet" | gawk '/be+t/{print $0}'
beeet
$ echo "beat" | gawk '/b[ae]+t/{print $0}'
beat
20.3.2 加号
ERE中的花括号允许你为可重复的正则表达式指定一个上限,这通常称为间隔(interval),可以用两种格式来指定区间。
m
:正则表达式准确出现m
次。
m, n
:正则表达式至少出现m
次,至多n
次。
$ echo "beet" | gawk --re-interval '/be{1,2}t/{print $0}'
beet
$ echo "beat" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
beat
20.3.4 管道符号
管道符号允许你在检查数据流时,用逻辑OR
方式指定正则表达式引擎要用的两个或多个模式。
$ echo "The dog is asleep" | gawk '/cat|dog/{print $0}'
The dog is asleep
20.3.5 表达式分组
将分组和管道符号一起使用来创建可能的模式匹配组是很常见的做法。
$ echo "cat" | gawk '/(c|b)a(b|t)/{print $0}'
cat
20.4 正则表达式实战
20.4.1 目录文件计数
它会对PATH环境变量中定义的目录里的可执行文件进行计数,要这么做的话,首先你得将PATH变量解析成单独的目录名。
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/
local/games
然后可以打印对应的目录-目录下的文件数量
#!/bin/bash
# count number of files in your PATH
mypath=$(echo $PATH | sed 's/:/ /g')
count=0
for directory in $mypath
do
check=$(ls $directory)
for item in $check
do
count=$[ $count + 1 ]
done
echo "$directory - $count"
count=0
done
20.4.2 验证电话号码
正则表达式通常用于验证数据,确保脚本中数据格式的正确性。 一个常见的数据验证应用就是检查电话号码。数据输入表单通常会要求填入电话号码,而用户输入格式错误的电话号码是常有的事。在美国,电话号码有几种常见的形式:
(123)456-7890
(123) 456-7890
123-456-7890
123.456.7890
第一组数字首先左括号有也可能没有 ^\(?
,然后紧接着就是3位区号,区号以数字2开始^\(?[2-9][0-9]{2}
,然后会有一个右括号可能有可能没有,即^\(?[2-9][0-9]{2}\)?
。
第二组数字承接在第一组数字之后,可能有空格、单破折线或者点,因此(| |-|\.)
。然后是三位数字,即(| |-|\.)[0-9]{3}
。
第三组数字仍然需要匹配一个空格、单破折线或者点,即(| |-|\.)
,最后匹配4位本地电话分机号(| |-|\.)[0-9]{4}$
综上^\(?[2-9][0-9]{2}\)?(| |-|\.)[0-9]{3}(| |-|\.)[0-9]{4}$
然后在gawk程序中使用正则表达式间隔时,使用–re-interval命令行选项,得到正确的结果。
20.4.2 解析邮件地址
邮件基本格式:username@hostname
username值可以专门用这个方式匹配:^([a-zA-Z0-9_\-\.\+]+)@
hostname值也可以用同样方法匹配:^([a-zA-Z0-9_\-\.]+)
最后顶级域名只能是字母字符,必须不少于二个字符(国家
或地区代码中使用),并且长度上不得超过五个字符:\.([a-zA-Z]{2,5})$
放在一起就是:^([a-zA-Z0-9_\-\.\+]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$