写在前面:
正则表达式接触的不多,从接触的用法来看主要用于搜索、匹配,主要包括文件名、文件内容。可用于shell脚本中,但是没怎么用过。。。
最常用的是我们想从当前目录下查找文件名中包含hello的文件
ls -R |grep hello
当然还是使用find或locate查找文件更方便
/*find在当前目录下查找*/
find ./ -name hello*
/*locate在数据库中查找,查找很快*/
locate hello
当然可以用于不打开文件搜寻文件中是否包含我们想要的字符
/*在hello.c文件中搜寻是否包含hello字符*/
/*a- 利用cat+grep*/
cat hello.c |grep hello
/*b- 直接用grep或egrep,语法:
grep -n 搜寻字符 文件
其中-n表示显示字符在文件的行号*/
grep -n hello hello.c
学习目标:
掌握正则表达式匹配符的基本用法,包括
1- 掌握字符匹配符用法。* . [ - ] [^] | () \< \>
2- 掌握数量匹配符用法。* ? + {n} {n,\} {n,m}
3- 掌握位置匹配符。 ^ $
4- 掌握匹配模式\n
总结
使用grep练习正则表达式要加上-E参数,不然有些匹配不到。(?;+;{}; ();),且这几种情况在单引号内。或直接用egrep替换grep -E。这是一个坑,一定注意!
统一用法:使用egrep,待搜寻字符在单引号内。
重复次数向上兼容。比如3-5次,多于5次也满足要求。
主要关注常用的:字符类:. ;[] ;[-] ;[^]
正文
说明,为方便表达,xxx代表一个文件。例如一个hello.c可用xxx表示。下面表示在hello.c中搜索的以a开头的字符
egrep '^a' xxx
ubuntu下有个usr/share/dict/words文件,可用于正则表达式练习。
1- 字符匹配(加不加-E都可以)
. | 匹配除换行符 \n 之外的任何单字符,可以使用多个.表示匹配多个任意字符。egrep 'a...' xxx,表示匹配axxx字符。 |
[] | 匹配一个字符集。示例grep -E [abc] xxx,可匹配到a、b、c、ab、ac、bc、abc,即含有a、b、c任一个字符的都会被匹配到。 []常搭配-一块使用。egrep '[a-z]b' xxx,可匹配到小写字符+b的字符,如ab,bb... |
^ | 在[]中使用表示非。egrep '[^abc]' xxx,和[]相反,不匹配单字符a、b、c;不匹配双字符ab、ac、bc;不匹配三字符abc(试下就知道了,可能不是你想的)。但是abcd之类的会被匹配到,因为除了abc外还有其他字符。 |
| | 或逻辑。示例如下 |
\ | 转义字符,和C语言中一样 |
() | 子表达式。标记一个子表达式的开始和结束位置。。和数学里的括号一样,是一个整体,结合下面数量匹配一块使用。 |
\< \> | 单词。正则表达式中的单词和我们认识的不一样,指非单词字符分隔的字符串。单词字符指:字母、数字、下划线。 |
[[:upper:]] | 大写。egrep '[::upper:]]b' xxx,匹配大写字母+b的字符,形如Ab,Bb... |
其他[[: :]]之类的描述了解即可。
[[:alpha:]] | 任何字母 |
[[:digit:]] | 任何数字 |
[[:alnum:]] | 任何字母和数字 |
[[:space:]] | 任何空白字符 |
[[:upper:]] | 任何大写字母 |
[[:lower:]] | 任何小写字母 |
[[:punct:]] | 任何标点符号 |
[[:xdigit:]] | 任何16进制的数字,相当于[0-9a-fA-F] |
或逻辑示例,在hello.c文件中查找Jan或Jan. 或January字符
/*注意待搜寻字符用单引号*/
egrep 'Jan(uary| |\.)' hello.c
单词示例,在usr/share/dict/words文件中查找以at结尾的单词。除了可以搜到cat等单词,还搜到了cat's,因为cat以非字符空格和单引号分隔,符合单词解释。另外对于单词\<单词\>记忆解为两个转义字符,<单词>。
注意:单词后面的是标点符号!!
root@ubuntu:/home/lhk/learn_data/share/share_with_vmware/shell# egrep '\<[a-z]at\>' /usr/share/dict/words
bat
bat's
cat
cat's
eat
fat
fat's
hat
hat's
mat
mat's
oat
oat's
pat
pat's
rat
rat's
sat
tat
vat
vat's
单词后面的是标点符号举例: 匹配单词xat+任意个点,因为单词被非单词字符分隔,所以单词后面的点不是字符,只能是标点。
egrep '\<[a-z]at\>'.* hello.c
2- 数量匹配
注意关键字,是表达式前面的字符匹配的次数!!
使用\{}之类的,要将待匹配的字符放到单引号内!!
* | 匹配前面的子表达式零次或多次。egrep 'a*' xxx,有a无a都会匹配到,也就是匹配任意字符(注意!!) |
? | 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。egrep 'a?' xxx,匹配a出现0次或1次,多于1次的也匹配,这里就是匹配所有的字符。 |
+ | 匹配前面的子表达式一次或多次。egrep 'a+' xxx 匹配a不少于1次的字符 |
egrep,或grep -E
{n} | 重复出现n次。grep -E ‘a\{3\}’ xxx,匹配a重复出现3次,包含多余三次。 |
{n,} | 重复出现不少于n次。grep -E ‘a{3,}’ xxx,匹配重复a不少于3次的 |
{n,m} | 重复不少于n次不大于m次,但是如果多于m次也会匹配到。grep -E ‘a{3,5}’ xxx,匹配a重复3-5次的,多余5次也会匹配 |
可结合()使用
egrep '(ab){3,}' xxx //匹配ab重复不少于3次的
grep不使用-E参数
\{n\} | 重复出现n次。grep ‘a\{3\}’ xxx,匹配a重复出现3次,包含多余三次。 |
\{n,\} | 重复出现不少于n次。grep ‘a\{3,\}’ xxx,匹配重复a不少于3次的 |
\{n,m\} | 重复不少于n次不大于m次,但是如果多于m次也会匹配到。grep ‘a\{3,5\}’ xxx,匹配a重复3-5次的,多余5次也会匹配 |
3- 位置限定
$ | 匹配字符串结尾位置。 |
^ | a- 匹配字符串的开始位置。 b- 在方括号表达式中使用,表示除xxx之外 |
示例在hello.c文件中匹配以a开头,z结尾的字符。
egrep '^a[a-z]*z$' hello.c
4- 其他
匹配模式:匹配模式指匹配的子表达式。用\n表示,其中n为第n个子表达式。还记得,子表达式用括号括起来?
示例:
/*第一个子表达式为a,匹配aba*/
egrep '(a)b\1' hello.c
/*第2个子表达式为a,匹配abb*/
egrep '(a)(b)\2' hello.c
复杂示例:
/*共有两个子表达式(\<.*\>)和( ),分解:
(\<.*\>):第一个子表达式。\<单词\>,单词为.*,即不少于1个的字符
.? :0个或1个的句点。还记得,单词前后为标点吗
( )*:第二个子表达式,匹配任意个空格
\1:匹配第1个子表达式,也就是匹配单词。
*/
egrep '(\<.*\>).?( )*\1'
匹配文件、结果。很诧异为何匹配不到aa????
root@ubuntu:/home/lhk/learn_data/share/share_with_vmware/shell# cat hello.c
aa
a a
a a
a.a
a. a
a. ba
ab. a
a. ba
a. b
root@ubuntu:/home/lhk/learn_data/share/share_with_vmware/shell# egrep '(\<.*\>).?( )?\1' hello.c
a a
a a
a.a
a. a
附:
(1)匹配日期格式YYYY-MM-DD "[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}"
(2)匹配IP地址XXX.XXX.XXX "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}"
(3)匹配腾讯QQ号码 "[1-9][0-9]\{4,9\}"
下面的博客总结的很好,没有例子。