正则表达式
#正则表达式
定义正则表达式
正则表达式基础
扩展正则表达式
创建正则表达式
一、定义:正则表达式是你所定义的模式模板,能够在处理数据时使用正则表达式对数据进行模式匹配。正则表达式模式利用通配符来描述数据流中的一个或多个字符。
$ ls -al da*
二、正则表达式基础
1、正则表达式类型
正则表达式是通过正则表达式引擎实现的,流行的有两种: POSIX基础正则表达式(basic regular expression,BRE)引擎; POSIX扩展正则表达式(extended regular expression,ERE)引擎
sed编辑器只符合了BRE引擎规范的子集,这是出于速度方面的考虑导致的。
gawk程序用ERE引擎来处理它的正则表达式模式
2、BRE
第一条原则:正则表达式模式都区分大小写
①纯文本
$ echo "This is a test" | sed -n '/this/p'
$ -- 大小写不符,未匹配
$ echo "The books are expensive" | sed -n '/book/p' -- 在正则表达式中,你不用写出整个单词
The books are expensive
$ echo "This is line number 1" | sed -n '/ber 1/p' -- 使用空格加数字。在正则表达式中,空格和其他的字符并没有什么区别
This is line number 1
②特殊字符
正则表达式识别的特殊字符包括:
.*[]^${}\+?|()
不能在文本模式中单独使用这些字符,需要转义反斜线(\)
$ cat data2
The cost is $4.00
$ sed -n '/\$/p' data2 -- 查找文本中的$,因为$是特殊字符,所以需要转义
The cost is $4.00
在sed编辑器或gawk程序中,正斜线(/)虽然不是特殊字符但也需要转义
$ echo "3 / 2" | sed -n '/\//p'
3 / 2
③锚字符
行首锚点:锁定在行首,脱字符( ^ )定义从数据流中文本行的行首开始的模式
$ echo "Books are great" | sed -n '/^Book/p'
Books are great
行尾锚点:锁定在行尾,特殊字符美元符( $ )定义了行尾锚点
$ echo "This is a good book" | sed -n '/book$/p'
This is a good book
组合锚点
$ 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
$
$ cat data5
This is one test line.
This is another test line.
$ sed '/^$/d' data5 -- 过滤掉数据流中的空白行,使用d删除
This is one test line.
This is another test line.
④点号字符
特殊字符点号用来匹配除换行符之外的任意单个字符。它必须匹配一个字符,如果在点号字符的位置没有字符,那么模式就不成立
$ cat data6
This is a test of a 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.
$ sed -n '/.at/p' data6
The cat is sleeping.
That is a very nice hat.
This test is at line four.
$
⑤字符组
使用方括号来定义一个字符组。方括号中包含所有你希望出现在该字符组中的字符
$ sed -n '/[ch]at/p' data6
The cat is sleeping.
That is a very nice hat.
$ echo "Yes" | sed -n '/[Yy][Ee][Ss]/p' -- 可以使用多个字符组
Yes
$ cat data8
60633
46201
223001
4353
22203
$ sed -n '
> /^[0123456789][0123456789][0123456789][0123456789][0123456789]$/p -- 只匹配五位数,需要使用首尾锚点
> ' data8
60633
46201
22203
$
⑥排除型字符组
字符组的开头加个脱字符(^),可以寻找组中没有的字符
$ sed -n '/[^ch]at/p' data6
This test is at line four. -- 空格也属于字符,所以能够输出
⑦区间
可以用单破折线符号在字符组中表示字符区间
$ sed -n '/^[0-9][0-9][0-9][0-9][0-9]$/p' data8 -- 简化有效邮编查看
60633
46201
45902
$ sed -n '/[c-h]at/p' data6 -- 也适用于字母
The cat is sleeping.
That is a very nice hat.
$ sed -n '/[a-ch-m]at/p' data6 -- 还可以在单个字符组指定多个不连续的区间a-c、h-m
The cat is sleeping.
That is a very nice hat.
⑧特殊的字符组
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 "abc" | sed -n '/[[:alpha:]]/p'
abc
⑨星号
在字符后面放置星号表明该字符必须在匹配模式的文本中出现0次或多次
$ echo "iek" | sed -n '/s*/p' -- 任意字符后跟*都会输出,判断该字符出现和不出现的情况都是成立的
iek
$ echo "I'm getting a color TV" | sed -n '/colou*r/p' -- 模式中的 u* 表明字母u可能出现或不出现在匹配模式的文本中。用于单词错误拼写
I'm getting a color TV
$ echo "this is a regular pattern expression" | sed -n '
> /regular.*expression/p' -- 点号特殊字符和星号特殊字符组合起来,能够匹配任意数量的任意字符
this is a regular pattern expression
$ echo "btt" | sed -n '/b[ae]*t/p' -- [ae]*出现0次,成立
btt
$ echo "baakeeet" | sed -n '/b[ae]*t/p'
$ -- [ae]* ae的任意组合都成立,但a、e中不能有其他字符
三、扩展正则表达式
①问号
问号表明前面的字符可以出现0次或1次,不会匹配多次出现的字符
$ echo "bt" | gawk '/be?t/{print $0}'
bt
$ echo "bet" | gawk '/be?t/{print $0}'
bet
$ echo "beet" | gawk '/be?t/{print $0}'
$ -- 不会匹配出现 1 次以上的情况
$ echo "bt" | gawk '/b[ae]?t/{print $0}'
bt
$ echo "bat" | gawk '/b[ae]?t/{print $0}'
bat
$ echo "bot" | gawk '/b[ae]?t/{print $0}'
$
$ echo "bet" | gawk '/b[ae]?t/{print $0}'
bet
$ echo "baet" | gawk '/b[ae]?t/{print $0}'
$
$ echo "beat" | gawk '/b[ae]?t/{print $0}'
$
$ echo "beet" | gawk '/b[ae]?t/{print $0}'
$ -- 如果两个字符都出现了,或者其中一个字符出现了2次,模式匹配不成立
②加号
加号表明前面的字符可以出现1次或多次,但必须至少出现1次
$ echo "beeet" | gawk '/be+t/{print $0}'
beeet
$ echo "beet" | gawk '/be+t/{print $0}'
beet
$ echo "bet" | gawk '/be+t/{print $0}'
bet
$ echo "bt" | gawk '/be+t/{print $0}'
$
$ echo "bt" | gawk '/b[ae]+t/{print $0}' -- 同样适用于数组
$
$ echo "bat" | gawk '/b[ae]+t/{print $0}'
bat
$ echo "bet" | gawk '/b[ae]+t/{print $0}'
bet
$ echo "beat" | gawk '/b[ae]+t/{print $0}'
beat
$ echo "beet" | gawk '/b[ae]+t/{print $0}'
beet
$ echo "beeat" | gawk '/b[ae]+t/{print $0}'
beeat
③使用花括号
ERE中的花括号允许你为可重复的正则表达式指定一个上限
m :正则表达式准确出现 m 次。
m, n :正则表达式至少出现 m 次,至多 n 次。
$ echo "bt" | gawk --re-interval '/be{1}t/{print $0}'
$
$ echo "bt" | gawk --re-interval '/be{1,2}t/{print $0}'
$
$ echo "bet" | gawk --re-interval '/be{1,2}t/{print $0}'
bet
$ echo "beet" | gawk --re-interval '/be{1,2}t/{print $0}'
beet
$ echo "beeet" | gawk --re-interval '/be{1,2}t/{print $0}'
$
$ echo "bt" | gawk --re-interval '/b[ae]{1,2}t/{print $0}' -- 适合于数组
$
$ echo "bat" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
bat
$ echo "bet" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
bet
$ echo "beat" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
beat
$ echo "beet" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
beet
$ echo "beeat" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
$
$ echo "baeet" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
$
$ echo "baeaet" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
$
④管道符号
管道符号允许你在检查数据流时,用逻辑 OR 方式指定正则表达式引擎要用的两个或多个模式。如果任何一个模式匹配了数据流文本,文本就通过测试
$ echo "The dog is asleep" | gawk '/cat|dog/{print $0}'
The dog is asleep
$ echo "The sheep is asleep" | gawk '/cat|dog/{print $0}'
$
$ echo "He has a hat." | gawk '/[ch]at|dog/{print $0}'
He has a hat.
⑤表达式分组
当你将正则表达式模式分组时,该组会被视为一个标准字符
$ echo "Sat" | gawk '/Sat(urday)?/{print $0}'
Sat
$ echo "Saturday" | gawk '/Sat(urday)?/{print $0}'
Saturday
$
$ echo "cat" | gawk '/(c|b)a(b|t)/{print $0}'
cat
$ echo "cab" | gawk '/(c|b)a(b|t)/{print $0}'
cab
$ echo "bat" | gawk '/(c|b)a(b|t)/{print $0}'
bat
$ echo "bab" | gawk '/(c|b)a(b|t)/{print $0}'
bab
$ echo "tab" | gawk '/(c|b)a(b|t)/{print $0}'
$
$ echo "tac" | gawk '/(c|b)a(b|t)/{print $0}'
$
四、创建正则表达式
目录文件计数:
$
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
$
验证电话号码
美国的四种形式电话号码验证
(123)456-7890
(123) 456-7890
123-456-7890
123.456.7890
^\(?[2-9][0-9]{2}\)?(| |-|\.)[0-9]{3}( |-|\.)[0-9]{4}$
解析邮件地址
username@hostname
username 值可用字母数字字符以及以下特殊字符:
点号
单破折线
加号
下划线
hostname部分由一个或多个域名和一个服务器名组成
对于顶级域名,有一些特殊的规则。顶级域名只能是字母字符,必须不少于二个字符(国家或地区代码中使用),并且长度上不得超过五个字符
^([a-zA-Z0-9_\-\.\+]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$
生活就要逢山开路遇水搭桥,愿共勉!