字符串模式的使用

引言

Wolfram 语言中的一般符号字符串模式允许用户进行有效的字符串操作. 下面讨论字符串模式的细节,包括使用和实现的注意事项. 这里强调了帮助系统没有提到的一些问题.

Wolfram 语言的核心是用来描述一般表达式中模式的强大语言. 该语言用于函数定义,替代,和搜索,使用结构如 等等.
In[1]:=
Click for copyable input
Out[1]=
In[2]:=
Click for copyable input
Out[2]=
In[3]:=
Click for copyable input
Out[3]=
Wolfram 语言字符串模式使用相同的结构来描述文本字符串中的模式. 可以把字符串考虑为字符序列并且应用一般 Wolfram 语言模式原理. 另外还有一些有用的特定字符串模式结构.
In[4]:=
Click for copyable input
Out[4]=
In[5]:=
Click for copyable input
Out[5]=
In[6]:=
Click for copyable input
Out[6]=
规则表达式可以用作指定字符串模式的另一种方法. 该方法更紧凑,但可读性不强.
In[7]:=
Click for copyable input
Out[7]=
In[8]:=
Click for copyable input
Out[8]=
In[9]:=
Click for copyable input
Out[9]=

以下是识别字符串模式的一些函数.

StringMatchQ["s",patt]测试 s 是否与 patt 匹配
StringFreeQ["s",patt]测试 s 是否没有与 patt 匹配的子串
StringCases["s",patt]给出与 patt 匹配的 s 的子串列表
StringCases["s",lhs->rhs]使用 rhs 替换每个 lhs
StringPosition["s",patt]给出与 patt 匹配的子串位置列表
StringCount["s",patt]计算有多少个子串与 patt 匹配
StringReplace["s",lhs->rhs]替换每个与 lhs 匹配的子串
StringReplaceList["s",lhs->rhs]给出替代 lhs 的所有方式列表
StringSplit["s",patt]在每个与 patt 匹配的子串处分隔 s
StringSplit["s",lhs->rhs]lhs 处分隔,并在该位置插入 rhs

支持字符串模式的函数

一般字符串模式

一般字符串模式从模式对象形式的方式与 Wolfram 语言中一般模式对象相似. 为了联合几个字符串模式对象,使用 StringExpression 操作符 .
In[10]:=
Click for copyable input
Out[10]//FullForm=
StringExpressionStringJoin 紧密相关,除了允许使用nonstrings和不压平列表. 对于纯字符串,它们是等价的.
In[11]:=
Click for copyable input
Out[11]=

出现在字符模式中的对象列表与普通 Wolfram 语言模式列表紧密匹配. 关于字符串模式,字符串被认为是字符的序列,即可以认为 String[a,b,c],而普通模式结构应用于它.

下列对象可以在符号字符串模式中出现:

"string"由字符组成的字符串
_任意单个字符
__具有一个或多个字符的任意子串
___具有零个或多个字符的任意子串
x_,x__,x___给定名称 x 的子串
x:pattern给定名称 x 的模式
pattern..重复一次或多次的模式
pattern...重复零次或多次的模式
{patt1,patt2,}patt1|patt2|与至少一个 匹配的模式
patt/;condcond 等于 True 的模式
pattern?test对每个字符 test 等于 True 的模式
Whitespace空格字符序列
NumberString数字字符
DatePattern[spec]日期字符
charobj表示字符类的一个对象(见下)
RegularExpression["regexp"]与规则表达式匹配的子串
StringExpression[]任意字符串表达式

下列代表字符类:

{c1,c2,}任意
Characters["c1c2"]任意
CharacterRange["c1","c2"] 范围内的任意字符
HexadecimalCharacter十六进制数字 09, af, AF
DigitCharacter数字 09
LetterCharacter字母
WhitespaceCharacter空格,换行符,tab或其它空格符
WordCharacter字母或者数字
Except[p]除了与 p 匹配的任意字符

以下表示字符串中的位置:

StartOfString整个字符串的开头
EndOfString整个字符串的末尾
StartOfLine行的开头
EndOfLine行的末尾
WordBoundary单词字符和其它字符的分界
Except[WordBoundary]除了单词分界的任何位置

下面决定如果有几种可能的情况下,应该使用哪种匹配:

Shortest[p]p 的最短一致匹配
Longest[p]p 的最长一致匹配(默认)

下面讨论关于这些对象的一些重要问题.

与包含换行符在内的任意字符匹配. 为了与除了换行符(与规则表达式中的 "." 相似)以外的任意字符匹配,使用 Except["\n"]Except["\n"]..Except["\n"]....
In[12]:=
Click for copyable input
Out[12]=
In[13]:=
Click for copyable input
Out[13]=
In[14]:=
Click for copyable input
Out[14]=
模式列表,如 ,与其它方法如 的列表等价. 这在函数如CharactersCharacterRange 中是等价的,可用来指定字符类.
In[15]:=
Click for copyable input
Out[15]=
Condition)被使用时,考虑 Wolfram 语言的其余部分,涉及到的模式将作为字符串处理,因此在一些情况下,用户必须使用 ToExpression.
In[16]:=
Click for copyable input
Out[16]=
与普通 Wolfram 语言模式相似,PatternTest)中的函数用于每个单独的字符.
In[17]:=
Click for copyable input
Out[17]=
Whitespace 结构与 WhitespaceCharacter.. 等价.
In[18]:=
Click for copyable input
Out[18]=
可以在一个一般字符串模式中插入 RegularExpression 对象.
In[19]:=
Click for copyable input
Out[19]=
这里插入一个lookbehind约束(参见 "规则表达式")以确保只选出由 开头的单词.
In[20]:=
Click for copyable input
Out[20]=
StringExpression 对象可以嵌套.
In[21]:=
Click for copyable input
Out[21]=

对于字符串模式的 Except 结构采用可以表示单个字符或单个字符类的单一变量.

下面从字符串中删除非元音字符.
In[22]:=
Click for copyable input
Out[22]=
当试图匹配不同长度(如 )的模式时,首先尝试最长可能匹配. 为了迫使程序首先尝试最短匹配,用户必须把模式的相关部分封装在 Shortest[ ] 中.
In[23]:=
Click for copyable input
Out[23]=
In[24]:=
Click for copyable input
Out[24]=
如果由于某些原因,用户需要在短匹配中使用最长匹配,可以使用 Longest.
In[25]:=
Click for copyable input
Out[25]=
In[26]:=
Click for copyable input
Out[26]=
可以不使用 Longest 重写该模式.
In[27]:=
Click for copyable input
Out[27]=

规则表达式

规则表达式语法遵从内部的Perl兼容规则表达式库( Perl Compatible Regular Expressions library 或者 PCRE),它与Perl语法相近. (参见 [1] 以获得更多信息和文档). Wolfram 语言中的一个规则表达式由 RegularExpression 的头部表示.

下面基本元素可以用于规则表达式字符串:

c字符 c
.除了换行以外的任意字符
[c1c2]任意字符
[c1-c2]在范围 内的任意字符
[^c1c2]除了 外的任意字符
p*重复零次或多次的 p
p+重复一次或多次的 p
p?出现零次或一次的 p
p{m,n}重复 m 次和 n 次之间的 p
p*?,p+?,p??匹配的最短一致字符串
p*+,p++,p?+所有格匹配
(p1p2)与序列 , , 匹配的字符串
p1|p2 匹配的字符串

下面表示字符类:

\\d数字 09
\\D非数字
\\s空格,换行,tab或其它空格字符
\\S非空格字符
\\w单词字符 (字母,数字,或者
\\W非单词字符
[[:class:]]位于命名类中的字符
[^[:class:]]不位于命名类中的字符

可以使用下列命名类: alnumalphaasciiblankcntrldigitgraphlowerprintpunctspaceupperwordxdigit.

下面表示字符串中的位置:

^字符串(或者行)的开头
$字符串(或者行)的末尾
\\A字符串的开头
\\z字符串的末尾
\\Z字符串的末尾(首先允许单个换行字符)
\\b词边界
\\B除了词边界的任何位置

下面对所有规则表达式元素设置选项:

(?i)大写字母和小写字母等价处理(忽略大小写)
(?m)使 与行的开头和结尾匹配(多行模式)
(?s)允许 与换行符匹配
(?x)忽略所有空格键,并且把所有 之间的内容作为注释处理
(?-#c)未设置的选项

下面是lookahead/lookbehind结构:

(?=p)下面的文本必须与 p 匹配
(?!p)下面的文本不能匹配 p
(?<= p)前面的文本必须匹配 p
(?<!p)前面的文本必须匹配 p

下面是关于规则表达式一些问题的讨论.

这里寻找长度在2和4之间的单词字符子序列.
In[28]:=
Click for copyable input
Out[28]=
使用所有格量词 ,匹配会抓住尽可能多的字符,即使其余的模式需要,也不丢弃任何字符.
In[29]:=
Click for copyable input
Out[29]=
In[30]:=
Click for copyable input
Out[30]=
In[31]:=
Click for copyable input
Out[31]=
对应于十六进制数的字符.
In[32]:=
Click for copyable input
Out[32]=

用来在规则表达式中进行escape操作的字符的完整列表包括 , , , , , , , , , , , , . 例如,为了写出一个文本句号,使用 ,为了写出一个文本反斜线,使用 .

在字符类 中,用来进行escape操作的字符的完整列表是 , , , .

默认情况下, 分别匹配字符串的开头和结尾. 在多行模式下,这些匹配行的开头/结尾.
In[33]:=
Click for copyable input
Out[33]=
In[34]:=
Click for copyable input
Out[34]=
在多行模式下, 可以用来表示字符串的开头和结尾.
In[35]:=
Click for copyable input
Out[35]=
修饰符允许用户对规则表达式加入空格和注释,以增强可读性.
In[36]:=
Click for copyable input
Out[36]=
使用括号包围可以得到命名子模式,如 (subpatt),那么它们就成为编码子模式. 给定的子模式的数目等于从模式的开头计算开放括号数. 可以通过使用 \\n 指代子模式(模式中的第 n 个模式,或者通过规则中的右边中的 . 指的是所有匹配模式.
In[37]:=
Click for copyable input
Out[37]=
In[38]:=
Click for copyable input
Out[38]=
如果在该上下文中需要一个字母 (当左边的头部为 RegularExpression 时,用户可以使用反斜线(例如,).
In[39]:=
Click for copyable input
Out[39]=
如果在这些情况下,需要一个后面带有 字符的反斜线,则需要使用一些技巧,并暂时分成两个子字符串.
In[40]:=
Click for copyable input
Out[40]=
如果需要对一部分模式进行分组,但不想把组作为编号子模式计算,则使用 结构.
In[41]:=
Click for copyable input
Out[41]=

Lookahead和lookbehind 模式用以确保在不实际把文本包含为匹配的一部分的情况下,模式被匹配.

这里选出跟在字符串 后的单词.
In[42]:=
Click for copyable input
Out[42]=
这里试图在字符串中选出所有偶数数字,但是它将找到包含部分数字在内的匹配.
In[43]:=
Click for copyable input
Out[43]=
使用 lookbehind/lookahead,用户可以确保匹配前/后的字符不是数字(注意,lookbehind 测试在这种特殊情况下是多余的.
In[44]:=
Click for copyable input
Out[44]=

RegularExpression 与 StringExpression 的比较

在可用于一般符号字符串模式和用于规则表达式的不同模式对象之间有紧密的关联. 下面是写为规则表达式和符号字符串模式的模式实例列表.

规则表达式
一般字符串模式
解释
"abc""abc"字符串
"."Except["\n"]除了换行符以外的任意字符
"(?s)."_任意字符
"(?s).+"__一个或多个字符(贪心)
"(?s).+?"Shortest[__]一个或多个字符(非贪心)
"(?s).*"___零个或多个字符
".*"Except["\n"]...零个或多个字符(除了换行符)
"a?b""a"|""~~"b"带有一个 的零个或一个 (即 或者
"[abef]"Characters["abef"]任意字符 ,或者
"[abef]+"Characters["abef"]..一个或多个字符 ,或者
"[a-f]"CharacterRange["a","f"] 范围内的任意字符
"[^abef]"Except[Characters["abef"]]任意字符,除了 ,或者
"ab|efg""ab"|"efg"匹配字符串
"(ab|ef)gh""(?:ab|ef)gh"("ab"|"ef")~~"gh"带有 或者 (即 或者
"\\s"WhitespaceCharacter任意空格字符
"\\s+"Whitespace一个或多个空格字符
"(a|b)\\1"x:"a"|"b"~~x_将与 匹配
"\\d"DigitCharacter任意数字字符
"\\D"Except[DigitCharacter]任意非数字字符
"\\d+"DigitCharacter..一个或多个数字字符
"\\w"WordCharacter|"_"任意数字、字母或者 字符
"[[:alpha:]]"LetterCharacter任意字母字符
"[^[:alpha:]]"Except[LetterCharacter]任意非字母字符
"^abf""\\Aabc"StartOfString~~"abf"在字符串开头的字符串
"(?m)^abf"StartOfLine~~"abf"在行开头处的字符串
"wxz$""wxz\\z""wxz"~~EndOfString在字符串末尾处的字符串
"wxz\\Z""wxz"~~"\n"|""~~EndOfString在字符串末尾或字符串末尾的换行符之前的字符串

可用于一般字符串模式,而不能用于规则表达式的模式对象包含条件()和可以在匹配中范围一般 Wolfram 语言代码的模式测试().

在规则表达式中的一些特殊结构在一般字符串模式中不直接可用. 这些包括 lookahead/lookbehinds 以及给定长度的重复. 它们可以通过插入一个 RegularExpression 对象,嵌入一个较大的一般字符串模式.

字符串操作函数

下面讨论了在不同字符串操作函数中的一些特殊之处和微妙之处(这些函数的更多信息,请参见参考文献页面).

StringMatchQ

StringMatchQ 用来检查整个字符串是否与某个模式匹配.
In[45]:=
Click for copyable input
Out[45]=
In[46]:=
Click for copyable input
Out[46]=

StringMatchQ 是特别的,因为它允许元字符 作为通配符输入(为了后面兼容的原因). Shortest[___] 等价(RegularExpression["(?s).*?"])和 Except[CharacterRange["A","Z"]]RegularExpression["[^A-Z]"])等价.

下面三个模式是等价的.
In[47]:=
Click for copyable input
Out[47]=
In[48]:=
Click for copyable input
Out[48]=
In[49]:=
Click for copyable input
Out[49]=

注意,技术上说,这里 Shortest 的出现没有任何区别,由于我们只寻找可能的匹配.

如果用户需要范围模式中子模式匹配的字符串的各部,则必须使用 StringCases.

StringMatchQ 具有用来寻找允许小数目差异的匹配的 SpellingCorrection 选项.这个功能仅对于由单个字符串组成的模式有效.
In[50]:=
Click for copyable input
Out[50]=

StringFreeQ

StringFreeQ 用来检查一个字符串是否包含与模式匹配的子字符串. 用户不可以提取匹配子字符串;为了实现这个目的,用户可以使用 StringCases.
In[51]:=
Click for copyable input
Out[51]=
In[52]:=
Click for copyable input
Out[52]=

StringCases

StringCases 是用来在字符串中寻找模式出现次数,选出子模式并且处理结果的一般目的函数.

寻找与模式匹配的子串.
In[53]:=
Click for copyable input
Out[53]=
选出匹配子字符串.
In[54]:=
Click for copyable input
Out[54]=
In[55]:=
Click for copyable input
Out[55]=
限制匹配的数目.
In[56]:=
Click for copyable input
Out[56]=
可以使用规则列表.
In[57]:=
Click for copyable input
Out[57]=
用户也可以把字符串列表作为许多字符串有效处理的第一个变量(参见 "有效匹配的技巧" 以获得更多的讨论信息).
In[58]:=
Click for copyable input
Out[58]=
In[59]:=
Click for copyable input
Out[59]=

重叠选项

对于 StringCasesStringPositionStringCountOverlaps 选项处理在找到一个匹配后匹配器如何继续的问题. 它具有三个可能的设置:FalseTrue,或者 All. 对于 StringCasesStringCount,默认值是 False,而对于 StringPosition,默认值是 True.

使用 Overlaps->False,匹配器在接着上一个匹配子串的字符位置继续匹配测试.
In[60]:=
Click for copyable input
Out[60]=
使用 Overlaps->True,匹配器在上一个匹配子串后的字符位置继续(在涉及单个模式的情况下).
In[61]:=
Click for copyable input
Out[61]=
使用 Overlaps->All,匹配器保持从相同的位置开始,直到没有找到新的匹配.
In[62]:=
Click for copyable input
Out[62]=
如果在列表中给出多个模式,Overlaps->True 将使匹配器在进行到下一个字符前,对每个模式每次都从相同的位置开始.
In[63]:=
Click for copyable input
Out[63]=
In[64]:=
Click for copyable input
Out[64]=
注意,使用 Overlaps->True,在指定模式列表和使用其他操作符 之间有区别.
In[65]:=
Click for copyable input
Out[65]=
In[66]:=
Click for copyable input
Out[66]=

StringPosition

StringPositionStringCases 工作方式类似,除了返回的是匹配子串的位置.
In[67]:=
Click for copyable input
Out[67]=
In[68]:=
Click for copyable input
Out[68]=
默认情况下,Overlaps 选项是 True (参见 重叠选项 以获得该选项的更多信息).
In[69]:=
Click for copyable input
Out[69]=
注意,甚至是空字符串也可以匹配.
In[70]:=
Click for copyable input
Out[70]=

StringCount

StringCount 返回匹配的子串数目(可以使用 StringPositionStringCases)找到. 对于具有许多匹配的情况,用来存储所有子串的内存空间将成为问题,那么以上操作就是有用的.
In[71]:=
Click for copyable input
Out[71]=
In[72]:=
Click for copyable input
Out[72]=

注意,Overlaps->FalseStringCount 的默认值.

StringReplace

StringReplace 用于替代与给定模式匹配的子串.
In[73]:=
Click for copyable input
Out[73]=
命名模式可以用作替换规则右边的字符串. 注意在使用 RuleDelayed)时要避免不成熟的计算.
In[74]:=
Click for copyable input
Out[74]=
当使用规则表达式时,记住右边的 指的是整个匹配子串是方便的.
In[75]:=
Click for copyable input
Out[75]=
可以通过指定第三个变量,限制替代次数.
In[76]:=
Click for copyable input
Out[76]=
注意,替换不必是一个字符串. 如果结果不是一个字符串的话,返回 StringExpression.
Out[77]=
In[78]:=
Click for copyable input
Out[78]//FullForm=

对于使用联合了一般字符串模式的旧的 选项,这里我们提供了有限的支持,但是该选项不使用并且应该避免使用.

StringReplaceList

StringReplaceList 返回字符串列表,这里单个字符串的替代以各种可能的方式进行.
In[79]:=
Click for copyable input
Out[79]=
如果字符串列表作为输入给出,那么输出是结果的嵌套列表.
In[80]:=
Click for copyable input
Out[80]=

StringSplit

StringSplit 对于把字符串在与模式匹配的分隔符处分成许多字符串是有用的. 默认情况下,分隔在空格符的每次运行之间进行.
In[81]:=
Click for copyable input
Out[81]=
例如,为了把正常的句子分成单词,用户也需要在分隔符中加入标点符号.
In[82]:=
Click for copyable input
Out[82]=
默认情况下,在结果开头和末尾处的空串被删除.
In[83]:=
Click for copyable input
Out[83]=
这些也可以通过把 All 指定为第三个变量包含进来.
In[84]:=
Click for copyable input
Out[84]=
第三个变量也可以是一个数,它给出字符串分隔的最大子串数.
In[85]:=
Click for copyable input
Out[85]=
这里把字符串分成多个单行.
In[86]:=
Click for copyable input
Out[86]=
用户也可以在与位置如 StartOfLine 匹配的模式处分割. 这里在结果中保留换行符.
In[87]:=
Click for copyable input
Out[87]=
在输出中,通过把规则作为第二个变量使用,用户可以保留分隔符,或分隔符的各部.
In[88]:=
Click for copyable input
Out[88]=
In[89]:=
Click for copyable input
Out[89]=
In[90]:=
Click for copyable input
Out[90]=
In[91]:=
Click for copyable input
Out[91]=
用户也可以给出模式和规则列表;与模式匹配的分隔符将不出现在结果中.

对于Perl用户

概况浏览

除了一般字符串模式外,Wolfram 系统可以是Perl或Python等语言的许多日常普通编程任务的强大替代. 对于熟悉Perl语法,以及Perl进行字符串操作的方式的用户,下面的概要显示如何熟悉 Wolfram 系统中相同的功能.

下面是涉及类Perl函数的 Wolfram 系统函数的概括浏览.

Perl 结构
Wolfram 语言函数
解释
m/ .../StringFreeQStringCases把字符串与规则表达式匹配,可能提取子模式
s/ .../ .../StringReplace替换与规则表达式匹配的子串
split(...)StringSplit在与规则表达式匹配的分隔符处分隔字符串
tr/ .../ .../StringReplace用其它字符替换字符
/iIgnoreCase->True"(?i)"与大小写无关的修饰符
/s"(?s)"迫使 匹配所有字符(包括换行符)
/x"(?x)"忽略空格键,并且在规则表达式中允许扩展注释
/m"(?m)"多行模式 ( 匹配行的开头/末尾)

下面是关于一些普通Perl结构更详细的讨论.

m/.../

匹配操作符 测试一个字符串是否包含与 匹配的子串. 在 Wolfram 语言中对于这种简单匹配,可以使用 StringFreeQ.

下面是测试一个字符串是否包含 后某处的 Perl 代码片断.
下面是同样测试的 Wolfram 语言版本.

如果接下来需要访问被匹配的字符串的各部,在Perl中使用 , , ,可用的最好的 Wolfram 语言函数基本上是StringCases.

这是提取错误信息的Perl代码.
这是一个 Wolfram 语言版本.
这是一次性提取几个子模式的Perl代码.
在 Wolfram 语言中,这使用 StringCases 实现.
In[97]:=
Click for copyable input
Out[98]=
这与使用 修饰符对一个阵列赋以所有匹配类似.
在 Wolfram 语言中可以使用 StringCases 实现同样功能.
In[99]:=
Click for copyable input
Out[100]=

s/.../.../

Perl 中 替换操作符的明显的 Wolfram 语言版本是StringReplace.
默认 Perl 行为是进行单一替换.
In[101]:=
Click for copyable input
Out[102]=
Perl中的 修饰符进行所有匹配的全局替换.
In[103]:=
Click for copyable input
Out[103]=
使用计算 修饰符,Perl可以把子模式作为替换操作的部分使用. 在 Wolfram 语言中,这是很容易实现的.
In[104]:=
Click for copyable input
Out[105]=

split(...)

Perl 中的 命令与 Wolfram 语言中的 StringSplit 相似.
In[106]:=
Click for copyable input
Out[107]=
可以在 Perl 和 Wolfram 语言中可以指定分成的块数目.
In[108]:=
Click for copyable input
Out[108]=
在模式中用来捕获括号的 ,捕获的子串被包括在结果中,可以在 Wolfram 语言中使用StringSplit 的第二个变量中的规则来实现. 与Perl相比较,在 Wolfram 语言中,把函数用于这些子串是容易的.

tr/.../.../

Perl 命令可以使用 Wolfram 语言 StringReplace 以及合适的规则列表模拟.

以下是字符 分别被 替换的最简单形式.
这里在 Wolfram 语言中使用 Thread 产生合适的规则.
In[113]:=
Click for copyable input
Out[114]=
以下例子中,替换列表比字符列表短,因此 全部被 替代.
In[115]:=
Click for copyable input
Out[116]=
Perl 中的字符范围在 Wolfram 语言中使用 CharacterRange 仿效.
In[117]:=
Click for copyable input
Out[118]=
使用 修饰符,多于的字符被删除.
In[119]:=
Click for copyable input
Out[120]=
使用 修饰符,字符列表的补集被采用.
In[121]:=
Click for copyable input
Out[121]=
In[122]:=
Click for copyable input
Out[122]=
修饰符挤压到翻译成同样字符的任意字符串序列.    
Wolfram 语言 中可以使用 Repeated)获得同样的效果.
In[123]:=
Click for copyable input
Out[124]=

一些示例

字符串模式的实际应用的简要示例在该章节中讨论.

高亮模式(Highlight Patterns)

这里定义了基数为1000的随机DNA字符串.
In[125]:=
Click for copyable input
Out[125]=
这里对匹配某种模式的DNA片段使用高亮突出显示.
In[126]:=
Click for copyable input
Out[126]=
下面是使用规则表达式的相同结果.
In[127]:=
Click for copyable input
Out[127]=

HTML解析

字符串模式对于采用原始HTML和从中提取信息非常有用.

下面是来自 www.google.com 的源代码.
In[134]:=
Click for copyable input
In[135]:=
Click for copyable input
Out[135]=
下面从源代码中提取所有直接超链接.
In[136]:=
Click for copyable input
Out[136]=
这里删除在标签 <> 中的所有信息.
In[137]:=
Click for copyable input
Out[137]=

寻找货币

以下是扫描字符串寻找美元数额的一些文本.
In[138]:=
Click for copyable input
Out[138]=
以下是使用符号字符串模式进行搜索的方法.
In[139]:=
Click for copyable input
Out[139]=
以下是使用规则表达式的相同搜索(注意,必须记住对美元符号进行escape操作).
In[134]:=
Click for copyable input
Out[134]=
这也是一个内置模式对象,对于该特殊情况为 NumberString.
In[141]:=
Click for copyable input
Out[141]=

在文件中寻找文本

这是一个用来在包含与给定模式匹配的文本中,寻找行的很简单的类grep函数.
In[142]:=
Click for copyable input
这里创建了一个样本文本文件.
In[143]:=
Click for copyable input
Out[143]=
这里返回 中包含任意数字字符的行数和行.
In[138]:=
Click for copyable input
Out[138]//TableForm=
这里寻找把 作为独立单词的行.
In[139]:=
Click for copyable input
Out[139]//TableForm=

有效匹配的技巧

本章节讨论涉及字符串模式匹配中有效性的问题.

StringExpression 与 RegularExpression 的比较

由于 Wolfram 语言语法中的字符串模式很快被转化为一个规则表达式,并且被编译和保存,所以比起直接的规则表达式语法来说,使用 Wolfram 语言语法的开销很小. 一个例外情况是当许多不同模式被多次使用时;在那种情况下,开销可能会变得显著一些.

条件和模式测试

如果一个模式包含 Condition)或者 PatternTest)语句,一般 Wolfram 语言计算器必须在匹配过程中调用,因此会降低速度. 如果不使用这样的结构写模式的话,通常速度会更快.
In[140]:=
Click for copyable input
In[141]:=
Click for copyable input
Out[141]=
In[142]:=
Click for copyable input
Out[142]=

避免嵌套量词

由于在匹配中使用非确定性有限自动机算法(NFA),涉及嵌套量词(如 或规则表达式)的模式可以变得任意缓慢. 这样的模式经常可以被打开成更有效的版本(见 Friedl [2] 以获得更多信息.

避免对函数的多次调用

如果用户在整个字符串长列表中寻找匹配,一次性把整个列表传给字符串函数更为有效,而不使用一些比如 SelectStringMatchQ 的操作(具体演示,参见更前面的字典示例). 以下示例产生2000个字符串的列表,每个字符串具有10个字符,并且搜寻以 开头并且包含 作为子串的字符串.
In[143]:=
Click for copyable input
In[144]:=
Click for copyable input
Out[144]=
以下是较慢的版本,使用 SelectStringMatchQ.
In[145]:=
Click for copyable input
Out[145]=
如果现在用户把整个列表一次性传给 StringMatchQ,速度将更快. 那么 Pick 可以用来提取想要的元素.
In[146]:=
Click for copyable input
Out[146]=
相反地,用户可以使用 StringCases,也很快. 注意,用户必须使用 StartOfString 固定模式,来确保 在开头(在这种特殊情况下,EndOfString 是多余的).
In[147]:=
Click for copyable input
Out[147]=

把一般表达式搜索重写为字符串搜索

由于字符串匹配算法与用来做一般表达式匹配的 Wolfram 语言算法不同(例如,字符串匹配可以假定一个有限的字母和平面结构),存在把普通表达式匹配问题转化为字符串匹配问题是有利的情况. 一个典型的情况是把符号的长列表与涉及 多次出现的模式匹配.

作为一个例子,假定用户想要寻找至少有4个相同数字的质数(如质数1000000). 使用普通的模式匹配,可以用如下方式完成.
In[148]:=
Click for copyable input
Out[148]=
通过把整数列表转换为一个字符串,用户可以使用字符串匹配.
In[149]:=
Click for copyable input
Out[149]=
通过前面使用 Pick 或者 StringCases 的技巧,用户可以更快地加快速度.
In[150]:=
Click for copyable input
Out[150]=
In[151]:=
Click for copyable input
Out[151]=
对于长序列,区别是显著的.
In[152]:=
Click for copyable input
In[153]:=
Click for copyable input
Out[153]=
In[154]:=
Click for copyable input
Out[154]=
In[155]:=
Click for copyable input
In[156]:=
Click for copyable input
Out[156]=
In[157]:=
Click for copyable input
Out[157]=

实现细节

Wolfram 语言中的字符串模式匹配建立于PCRE顶端(Perl 可兼容规则表达式)的库,作者为 Philip Hazel [1].

在一些情况下,使用前-5.1 Wolfram 系统算法(例如,当模式只是一个单独的字符串的时候).

任意符号字符串模式首先被翻译为一个规则表达式. 可以使用内部 函数查看翻译.

返回的第一个元素是规则表达式,而其余元素必须对条件、替换规则和命名模式进行操作.

接下来,规则表达式可以使用PCRE编译,然后编译了的版本被存储以备将来相同模式再次出现时使用. 从符号字符模式到规则表达式的转化只出现一次.

模式中的 Wolfram 语言条件由从PCRE库到 Wolfram 语言计算器的外部调用命令执行,因此这样会减缓匹配过程.

嵌入一个普通字符串模式的明确的 RegularExpression 对象将连接到一个最终的规则表达式(由括号形如 包围),因此,命名模式的数目将比用户所期待的更为倾斜.

由于PCRE目前不支持在字符码255之外的预调的字符类,单词和字母字符类(如 WordCharacterLetterCharacter)只包括Unicode范围在0-255之间的字符码. 因此,LetterCharacter_?LetterQ 不给出在字符码255之外的等价的结果.

由于相似的 PCRE 限制,忽略大小写的匹配 (例如,使用 IgnoreCase->True)将只应用于在Unicode范围位于0-127之内的字符(即,普通英文字母).

参考文献

[1] Hazel, P. "PCREPerl Compatible Regular Expressions." 2004. www.pcre.org

[2] Friedl, J. E. F. Mastering Regular Expressions, 2nd ed. O'Reilly & Associates, 2002.