加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

正则表达式之字符组

发布时间:2020-12-14 01:41:15 所属栏目:百科 来源:网络整理
导读:1 字符组 本节讨论的都是ASCII匹配规则,Unicode在第7节讨论。 1.1 普通字符组 Character Class就是一组字符,在正则表达式中,它表示“在同一个位置可能出现的各种字符”。 注意:本文用Python语言验证各种正则表达式的匹配。 例子1 用正则表达式判断数字字
  • 1 字符组
本节讨论的都是ASCII匹配规则,Unicode在第7节讨论。
  • 1.1 普通字符组
Character Class就是一组字符,在正则表达式中,它表示“在同一个位置可能出现的各种字符”。
注意:本文用Python语言验证各种正则表达式的匹配。

例子1 用正则表达式判断数字字符在各种语言中的应用
.NET(C#)
//能匹配则返回true,否则返回false
Regex.IsMatch(charStr,"[0123456789]");

Java
//能匹配则返回true,否则返回false
charStr.matchs("[0123456789]");

JavaScript
//能匹配则返回true,否则返回false
/[0123456789]/.test(charStr);

PHP
//能匹配则返回1,否则返回0
preg_match("/[0123456789]/",charStr);

Python
//能匹配则返回RegexObject,否则返回None
import re
re.search("[0123456789]",charStr);

Ruby
//能匹配则返回0,否则返回nil
charStr =~/[0123456789]/


默认情况下,re.search(pattern,string)只判断string的某个子串能否由pattern匹配,即使pattern只能匹配string的一部分,也不会返回None。如果需要完全匹配,在pattern两端加上^和$

# 只要字符串中包含数字字符,就可以匹配
>>> import re
>>> re.search("[0123456789]","2") != None
True
>>> re.search("[0123456789]","12") != None
True
>>> re.search("[0123456789]","a2") != None
True

# 整个字符串就是一个数字字符,才可以匹配
>>> re.search("^[0123456789]$","a2") != None
False
>>> re.search("^[0123456789]$","12") != None
False

字符组中的字符排列顺序并不影响字符组的功能,出现重复字符也不会影响。不过,代码总是要容易编写,方便阅读,所以一般不推荐在字符组中出现重复字符。而且,还应该让字符组中的字符排列更符合认知习惯,比如[0123456789]就好过[0192837465]。为此,正则表达式提供了-范围表示法(range)。

>>> import re
>>> re.search("^[0-9]$","2")!=None
True

>>> re.search("^[9-0]$","2")!=None

Traceback (most recent call last):
File "<pyshell#6>",line 1,in <module>
re.search("^[9-0]$","2")!=None
File "C:Python27libre.py",line 142,in search
return _compile(pattern,flags).search(string)
File "C:Python27libre.py",line 242,in _compile
raise error,v # invalid expression
error: bad character range

从上面的例子可以看出,[0-9]等价于[0123456789],而[9-0]则是错误的范围,因为9的ASCII码值是57,大于0的码值48.

如果想表示数字和字母,那么推荐使用[0-9a-z]而不是简单地使用[0-z],因为0-z之间还有标点符号和大写的A-Z。

例子 [0-z]的奇怪匹配

>>> re.search("^[0-z]$","A")!=None
True
>>> re.search("^[0-z]$",":")!=None
True

例子[0-9a-fA-F]准确判断十六进制字符
>>> re.search("^[0-9a-fA-F]$","0") != None
True
>>> re.search("^[0-9a-fA-F]$","c") != None
True
>>> re.search("^[0-9a-fA-F]$","i") != None
False
>>> re.search("^[0-9a-fA-F]$","C") != None
True
>>> re.search("^[0-9a-fA-F]$","G") != None
False

使用xhex表示一个字符,其中x是固定前缀,表示转义序列的开头,num是字符对应的码值,是一个两位的十六进制数值。依靠这种表示法可以很方便地匹配所有的中文字符。
例子 [x00-x7F]准确判断ASCII 字符

>>> re.search("^[x00-x7F]$","c")!= None
True
>>> re.search("^[x00-x7F]$","0")!= None
True
>>> re.search("^[x00-x7F]$","<")!= None
True

  • 1.2 元字符与转义
像范围表示法中的-,字符组的开方括号[、闭方括号]和之前出现的^、$都是元字符,在匹配中,它们有特殊的意义。但是,有时并不需要表示这些特殊意义,只需要表示普通字符,此时需要使用转义字符来做特殊处理。
例子 -出现在不同位置,含义不同
#作为普通字符
>>> re.search("^[-09]$","3")!=None
False
>>> re.search("^[-09]$","-")!=None
True

#作为元字符
>>> re.search("^[0-9]$","3")!= None
True
>>> re.search("^[0-9]$","-")!= None
False

#转义之后作为普通字符
>>> re.search("^[0-9]$","3")!= None
False
>>> re.search("^[0-9]$","-")!= None
True

我们注意到上面的转义字符中使用了两个,这是由于n,t之类的会被认为是转义序列(Escape Sequence),但-不是,所以在字符串中,需要使用表示转义。 (在Java、PHP、Python、.NET等语言中,正则表达式都是以字符串的形式给出的,在Ruby和JavaScript中则不是。)
在Python中,提供了原生字符串(Raw String),它非常适合于正则表达式,此时就不需要考虑正则表达式之外的转义。原生字符串的形式是r"string"。.NET和Ruby也提供了原生字符串。
例子 原生字符串的使用
#原生字符串和字符串的等价
>>> r"^[0-9]$" == "^[0-9]$"
True

#原生字符串的转义
>>> re.search(r"^[0-9]$","3") != None
False
>>> re.search(r"^[0-9]$","-") != None
True

例子 ]出现在不同位置,含义不同
#未转义的]
>>> re.search(r"^[012]345]$","2345") != None
False
>>> re.search(r"^[012]345]$","5") != None
False
>>> re.search(r"^[012]345]$","]") != None
False

#转义的]
>>> re.search(r"^[012]345]$","2345") != None
False
>>> re.search(r"^[012]345]$","5") != None
True
>>> re.search(r"^[012]345]$","]") != None
True

例子 取消其他元字符的特殊含义
>>> re.search(r"^[012]345]$","3")!= None
False
>>> re.search(r"^[012]345]$","3")!= None
True
>>> re.search(r"^[012]$","[012]")!= None
False
#只需要转义开方括号[,闭方括号]不需要转义。
>>> re.search(r"^[012]$","[012]")!= None
True
  • 1.3 排除型字符组
在开方括号[之后紧跟一个脱字符^,写作[^...]。

例子 使用排除型字符组
>>> re.search(r"^[^0-9][0-9]$","A8") != None
True
>>> re.search(r"^[^0-9][0-9]$","x6") != None
True

例子 排除型字符组必须匹配一个字符
>>> re.search(r"^[^0-9][0-9]$","8") != None
False
>>> re.search(r"^[^0-9][0-9]$","A8") != None
True

例子 在排除型字符组中,紧跟在^之后的-不是元字符
>>> re.search(r"^[^-09]$","-") != None
False
>>> re.search(r"^[^-09]$","8") != None
True

>>> re.search(r"^[^-09]$","-") != None
False
>>> re.search(r"^[^-09]$","8") != None
True

例子 排除型字符组的转义
>>> re.search(r"^[^012]$","^")!=None
True
>>> re.search(r"^[0^12]$","^")!=None
True
>>> re.search(r"^[^012]$","^")!=None
True

  • 1.4 字符组简记法
正则表达式对[0-9],[a-z]之类的字符组提供了简单的记法,称为字符组简记法(shorthands).常用的字符组简记法有d表示[0-9],w表示[0-9a-zA-Z_],s表示[ tnrvf]。
例子 字符组简记法d w s
>>> re.search(r"^d$","9")!=None
True
>>> re.search(r"^d$","a")!=None
False
>>> re.search(r"^w$","8")!=None
True
>>> re.search(r"^w$","a")!=None
True
>>> re.search(r"^w$","_")!=None
True
>>> re.search(r"^s$"," ")!=None
True
>>> re.search(r"^s$","t")!=None
True
>>> re.search(r"^s$","n")!=None
True

字符组简记法既可以单独使用,也可以使用在字符组中,比如[0-9a-zA-Z]也可以写作[da-zA-Z]。也可以使用在排除型字符组中,比如[^0-9]可以写作[^d]。

例子 字符组简记法与普通字符组混用
>>> re.search(r"^[da-zA-Z]$","8") != None
True
>>> re.search(r"^[da-zA-Z]$","a") != None
True
>>> re.search(r"^[da-zA-Z]$","C") != None
True
>>> re.search(r"^[^w]$","8")!=None
False
>>> re.search(r"^[^w]$","_")!=None
False
>>> re.search(r"^[^w]$",",")!=None
True

d,w,s对应的排除型字符组记为D,W,S。
例子 D W S的使用
#d和D
>>> re.search(r"^d$","8")!=None
True
>>> re.search(r"^d$","a")!=None
False
>>> re.search(r"^D$","8")!=None
False
>>> re.search(r"^D$","a")!=None
True
#w和W
>>> re.search(r"^w$","c")!=None
True
>>> re.search(r"^w$","!")!=None
False
>>> re.search(r"^W$","c")!=None
False
>>> re.search(r"^W$","!")!=None
True

#s和S
>>> re.search(r"^s$","0")!=None
False
>>> re.search(r"^S$","t")!=None
False
>>> re.search(r"^S$","0")!=None
True

[sS],[wW],[dD]都可以表示任意字符。在许多有关正则表达式的文档中,点号.能匹配“任意字符”。但在默认情况下,点号其实不能匹配换行符。当然可以在某些语言中开启单行模式(Single line),在这种模式下,所有文本似乎都在一行里,换行符是这一行中的“普通字符”,所以可以由.点号匹配。

  • 1.5 字符组运算
Java:
“a".matches("^[[a-z]&&[^aeiou]]$"); //False
"b".mattches("^[[a-z]&&[^aeiou]]$"); //True

  • 1.6 POSIX字符组
常用在Linux/UNIX下的各种工具(sed、AWK、grep等)中。之前介绍的都属于Perl衍生出来的正则表达式刘鹏,叫做 PCRE(Perl Compatible Regular Expression).而POSIX(Portable Operating System Interface for uniX),它是一系列规范,定义了UNIX操作系统应当指出的功能,其中也包括了关于正则表达式的规范,[:digit:]之类的字符组就是遵循POSIX规范的字符组。
常见的[a-z]形式的字符组,在POSIX规范中仍然获得支持,它的准确名称是POSIX方括号表达式(POSIX bracket expression),主要用在UNIX/Linux系统中。POSIX方括号表达式与PCRE的字符组最主要的差别在于:在POSIX字符组中,不是用来转义的。所以POSIX方括号表达式[d]只能匹配和d两个字符,而不是[0-9]对应的数字字符。
为了解决字符组中特殊意义字符的转义问题, POSIX方括号表达式规定:如果要在字符组中表达字符](而不是作为字符组的结束标记],应当让它紧跟在字符组的开方括号之后,所以[]a]能匹配的字符就是]或者a;如果要在字符组中标记字符-(而不是做为范围表示法),就必须将它放在字符组的闭方括号]之前,所以[a-]能匹配的字符就是a或-。


表 POSIX字符组(对应ASCII字符,下表不支持Unicode字符集)
POSIX字符组 说明 ASCII字符组 等级的PCRE简记法
[:alnum:] * 字母字符和数字字符 [a-zA-Z0-9]
[:alpha:] 字母 [a-zA-Z]
[:ASCII:] ASCII字符 [x00-x7F]
[:blank:] 空格字符和制表符 [ t]
[:cntrl:] 控制字符 [x00-x1Fx7F]
[:digit:] 数字字符 [0-9] d
[:graph:] 空白字符之外的字符 [x21-x7E]
[:lower:] 小写字母字符 [a-z]
[:print:] 类似[:graph:],但包括空白字符 [x20-x7E]
[:punct:] 标点符号 [][!"#$%@&'*(){}-+,./?:;<>=|~`]
[:space:] 空白字符 [ trnvf] s
[:upper:] 大写字母字符 [A-Z]
[:word:]* 字母字符 [a-zA-Z0-9_] w
[:xdigit:] 十六进制字符 [A-Fa-f0-9]
注:标记*的字符组简记法并不是POSIX规范中的,但使用很多,一般语言都提供。

JAVA、PHP、Ruby支持使用POSIX字符组。
在PHP中可以直接使用POSIX字符组,但是PHP的POSIX字符组只识别ASCII字符,任何非ASCII字符都不能有任何一个POSIX字符组匹配。
Ruby1.8中的POSIX字符组只匹配ASCII字符,而且不支持[:word:]和[:ASCII:];Ruby1.9中的POSIX字符组可以匹配Unicode字符,而且支持[:word:]和[:ASCII:]。
JAVA中,POSIX字符组必须使用p{Name}的形式,其中name为POSIX字符组对应的名称,比如[:digit:]就应该写作p{Digit},第一个字母要大写,其他POSIX字符组都是这样,只有[:xdigit:]就应该写作p{XDigit}.并且JAVA中的POSIX字符组只匹配ASCII字符。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读