正则表达式
1. 正则表达式
正则表达式是你所定义的模式模板(pattern template),linux工具用它来过滤文本
正则表达式通过正则表达式引擎(regular expression engine)实现,正则表达式引擎是一套底层软件,负责解释正则表达式模式并使用这些模式进行文本匹配
在linux中,有两种主流的正则表达式引擎:
POSIX基础正则表达式(basic regular expression,BRE)引擎
POSIX扩展正则表达式(extended regular expression,ERE)引擎
大多数linux工具至少符合BRE引擎规范,能够识别该规范定义的所有模式符号
2. BRE模式
纯文本:正则表达式区分大小写
正则表达式识别特殊字符包括:.*[]^${}\+?|()
如果要用某个特殊字符作为文本字符,就必须通过转义符(\
)进行转义
]# sed -n '/\$/p' data.txt
尽管/不是特殊字符,但是如果匹配该字符仍需转义
]# echo 'safsa/fsadf' |sed -n '/\//p'
safsa/fsadf
]# echo 'safsa/fsadf' |sed -n '///p'
sed: -e expression #1, char 3: unknown command: `/'
- 锚字符
2.1 锁定在行首
脱字符(^
)定义从数据流文本行中的行首开始的模式,格式:
^pattern
必须放在模式前,如果放在模式中的其他位置,将会视为普通字符
]# sed -n '/^Ad/p' data.txt
Adadsadfsad;df*$
2.2 锁定在行尾
美元符($
)定义了行尾锚点,格式
pattern$
必须放在模式后,同样放在模式中的其他位置,视为普通字符
]# sed -n '/9$$/p' data.txt
2629$
2.3 组合锚点
^和$组合
]# sed -n '/^262$$/p' data.txt
262$
]# sed -n '/^$/p' data.txt
匹配空行,删除空行
]# sed '/^$/d' data.txt
ASDLKFJASDKF
Adadsadfsad;df*$
2629$
262$
eecho12312412
_sfsadf222312#@
[root@localhost day8]# cat data.txt
ASDLKFJASDKF
Adadsadfsad;df*$
2629$
262$
eecho12312412
_sfsadf222312#@
2.4 点号字符
特殊字符点号(.
)用来匹配除了换行符之外的任意单个字符,它必须匹配一个字符
,如果在点号字符位置没有字符,则模式不匹配
]# sed -n '/2.29/p' data.txt
2629$
]# echo 'at this time'|sed -n '/.at/p'
]# echo 'hat this time'|sed -n '/.at/p'
hat this time
2.5 字符组
如果要限定待匹配的具体字符,称为字符组(character class)
如果字符组中的某个字符出现在了数据流中,它就匹配了模式
使用[]
来定义一个字符组,方括号中包含所有你希出现在该字符组中的字符
]# sed -n '/[4*#]/p' data.txt
Adadsadfsad;df*$
eecho12312412
_sfsadf222312#@
2.6 排除型字符组
在字符组开头加脱字符,起到反转字符组作用,正则表达式会匹配不包含在排除型字符组的字符,格式
[^xxx]
]# cat data.txt
This is a test of a line #不包含at,所以不匹配
the bcat is sleeping
That is a very nice hat
This test is at line four #空格也算字符,所以批评
at ten o'clock we'll go home #at前无字符,至少应有一个字符
]# sed -n '/[^ch]at/p' data.txt
This test is at line four
注意:即使是排除,字符组仍然必须匹配一个字符,空格也是字符
]# sed -n '/[^ch]at/p' data.txt
cat ,This test is at line four
特别注意:如果单行内容中,前部分匹配排除字符组,而后面有不匹配排除字符组,但能匹配模式的内容,仍能匹配,并非包含排除匹配后面不进行匹配
2.7 区间
根据linux采用的字符集,区间包括
数字区间[0-9]
字母区间[a-z][A-Z]
也可以指定区间[c-h]
,只能是上述区间子集
]# sed -n '/[a-d]at/p' data.txt
the bcat is sleeping
cat ,This test is at line four
2.8 特殊字符组
BRE特殊字符组:
组 | 描述 |
---|---|
[[:alpha:]] | 匹配任意字母字符,不管大小写,[a-z],[A-Z] |
[[: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 "hello,world"|sed -n '/[[:punct:]]/p'
hello,world
]# echo "hello world"|sed -n '/[[:punct:]]/p'
]# echo "hello world"|sed -n '/[[:space:]]/p'
hello world
2.9 星号
在字符后面放置星号(*
),表明该字符必须在匹配模式的文本中出现0次或多次
]# echo "hello world"|sed -n '/wor*ld/p'
hello world
]# echo "hello worrld"|sed -n '/wor*ld/p'
hello worrld
点星
组合
能够匹配任意数量的任意字符
]# echo "hello worrr sdaf ld"|sed -n '/w.*ld/p'
hello worrr sdaf ld
只要包含w在前,ld在后的字符串都匹配
星号和字符组
组合
允许指定可能在文本中不出现或出现多次的字符组或字符区间
但是只能字符区间内的字符,次数不限,出现其他字符则不匹配
]# echo 'bat' | sed -n '/b[ae]*t/p'
bat
]# echo 'bakt' | sed -n '/b[ae]*t/p'
]# echo 'baeeeeet' | sed -n '/b[ae]*t/p'
baeeeeet
3. ERE模式
gawk能识别ERE模式,sed不支持,所以单从处理数度来说,gawk要慢些
3.1 问号(?
)
问号表明前面字符可以出现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}'
3.2 加号(+
)
加号表明前面字符可以出现1次或多次
,至少出现1次
]# echo 'beet'|gawk '/be+t/{print $0}'
beet
3.3 花括号({}
)
ERE中花括号允许你为可重复的正则表达式指定一个上限,通常称为间隔(interval),可以使用两种格式指定区间
- {
m
}: 正则表达式准确出现m次 - {
m,n
}: 正则表达式至少出现m次,至多n次
gawk中必须指定–re-interval命令行选项才能识别间隔,默认无法识别
]# echo 'beet'|gawk '/be{2}t/{print $0}'
beet
[root@localhost day8]# echo 'beet'|gawk '/be{1,2}t/{print $0}'
beet
]# echo 'beet'|gawk '/be{2,3}t/{print $0}'
beet
]# echo 'beet'|gawk '/be{1}t/{print $0}'
]# echo 'beet'|gawk '/be{3,5}t/{print $0}'
注意:间隔为闭区间,两侧上下限均包含
区间仍适用
]# echo 'beet'|gawk '/b[ea]{2,3}t/{print $0}'
beet
]# echo 'beat'|gawk '/b[ea]{2,3}t/{print $0}'
beat
]# echo 'beaeat'|gawk '/b[ea]{2,3}t/{print $0}'
3.4 管道符号(|
)
管道符号允许你再检查数据流时,用逻辑OR方式指定正则表达式引擎要用的两个或多个模式,如果任何一个模式匹配,文本通过,格式
expr1|expr2|...
]# echo 'this cat sheep pig'|gawk '/cat|dog/{print $0}'
this cat sheep pig
]# echo 'this sheep pig'|gawk '/cat|dog/{print $0}'
3.5 分组表达式
正则表达式也可以用圆括号(())进行分组,当使用分组时,该组会被视为一个标准字符
]# echo 'this cat sheep pig'|gawk '/(ep)?/{print $0}'
this cat sheep pig
]# echo 'this cat sheep pig'|gawk '/(t s)?/{print $0}'
this cat sheep pig
]# echo 'this cat sheep pig'|gawk '/(t p)+/{print $0}'
组合
]# echo 'this cat sheep pig'|gawk '/(c|d)a(t|f)/{print $0}'
this cat sheep pig
]# echo 'this cat sheep pig'|gawk '/(c|d)a(e|f)/{print $0}'
4. 实例
- 统计PATH中定义的目录中可执行文件的数量
#!/bin/bash
mypath=$(echo $PATH|sed 's/:/ /g') #通过空格替换分隔符:,分隔PATH
#echo $mypath
count=0
for item in $mypath;do #迭代分隔后的PATH
diretory=$( ls $item) #列出每个目录中的可执行文件
for i in $diretory;do
count=$[ $count+1 ] #统计数量
done
echo "$item - $count"
count=0
done
- 验证电话号码
电话簿
]# cat phone
(123)456-7890
(123) 456-7890
223-345-7890
123.456.7890
电话简单要求:
1.以(或者数字开头
2.第一个数字必须时2-9,二三位必须是数字0-9
3.第四位必须是空格,-或者点
4.接着3位数字
5.接着必须是空格,-或者点
6.接着4位数字
]# cat iphone.sh
#!/bin/bash
gawk --re-interval '/^\(?[2-9][0-9]{2}\)?(| |-|\.)[0-9]{3}( |-|\.)[0-9]{4}$/{print $0}'
]# cat phone |./iphone.sh
223-345-7890