字符串模式的使用
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 |
"string" | 由字符组成的字符串 |
_ | 任意单个字符 |
__ | 具有一个或多个字符的任意子串 |
___ | 具有零个或多个字符的任意子串 |
x_
,
x__
,
x___ | 给定名称 x 的子串 |
x:pattern | 给定名称 x 的模式 |
pattern.. | 重复一次或多次的模式 |
pattern... | 重复零次或多次的模式 |
{patt1,patt2,…} 或 patt1patt2… | 与至少一个 patti 匹配的模式 |
patt/;cond | cond 等于 True 的模式 |
pattern?test | 对每个字符 test 等于 True 的模式 |
Whitespace | 空格字符序列 |
NumberString | 数字字符 |
DatePattern[spec] | 日期字符 |
charobj | 表示字符类的一个对象(见下) |
RegularExpression["regexp"] | 与规则表达式匹配的子串 |
StringExpression[…] | 任意字符串表达式 |
{c1,c2,…} | 任意 "ci" |
Characters["c1c2…"] | 任意 "ci" |
CharacterRange["c1","c2"] | 在 "c1" 到 "c2" 范围内的任意字符 |
HexadecimalCharacter | 十六进制数字 0–9, a–f, A–F |
DigitCharacter | 数字 0–9 |
LetterCharacter | 字母 |
WhitespaceCharacter | 空格,换行符,tab或其它空格符 |
WordCharacter | 字母或数字 |
Except[p] | 除了与 p 匹配的任意字符 |
StartOfString | 整个字符串的开头 |
EndOfString | 整个字符串的末尾 |
StartOfLine | 行的开头 |
EndOfLine | 行的末尾 |
WordBoundary | 单词字符和其它字符的分界 |
Except[WordBoundary] | 除了单词分界的任何位置 |
_、__ 和 ___ 与包含换行符在内的任意字符匹配. 为了与除了换行符(与规则表达式中的 "." 相似)以外的任意字符匹配,使用 Except["\n"]、Except["\n"].. 和 Except["\n"]...:
可以在一个一般字符串模式中插入 RegularExpression 对象:
StringExpression 对象可以嵌套:
对于字符串模式的 Except 结构采用可以表示单个字符或单个字符类的单一变量.
如果由于某些原因,用户需要在短匹配中使用最长匹配,可以使用 Longest:
可以不使用 Longest 重写该模式:
规则表达式语法遵从内部的 Perl 兼容规则表达式库(Perl Compatible Regular Expressions library 或 PCRE),它与 Perl 语法相近. (参见 [1] 以获得更多信息和文档). Wolfram 语言中的一个规则表达式由 RegularExpression 的头部表示.
c | 字符 c |
. | 除了换行以外的任意字符 |
[c1c2…] | 任意字符 ci |
[c1-c2] | 在范围 c1–c2 内的任意字符 |
[^c1c2…] | 除了 ci 外的任意字符 |
p* | 重复零次或多次的 p |
p+ | 重复一次或多次的 p |
p? | 出现零次或一次的 p |
p{m,n} | 重复 m 次和 n 次之间的 p |
p*?
,
p+?
,
p?? | 匹配的最短一致字符串 |
p*+
,
p++
,
p?+ | 所有格匹配 |
(p1p2…) | 与序列 p1, p2, … 匹配的字符串 |
p1p2 | 与 p1 或 p2 匹配的字符串 |
\\d | 数字 0–9 |
\\D | 非数字 |
\\s | 空格,换行,tab或其它空格字符 |
\\S | 非空格字符 |
\\w | 单词字符 (字母、数字或 _) |
\\W | 非单词字符 |
[[:class:]] | 位于命名类中的字符 |
[^[:class:]] | 不位于命名类中的字符 |
(?i) | 大写字母和小写字母等价处理(忽略大小写) |
(?m) | 使 ^ 和 $ 与行的开头和结尾匹配(多行模式) |
(?s) | 允许 . 与换行符匹配 |
(?x) | 忽略所有空格键,并且把所有 "#" 和 "\n" 之间的内容作为注释处理 |
(?-∖#c) | 未设置的选项 |
用来在规则表达式中进行escape操作的字符的完整列表包括 ., \, ?, (, ), {, }, [, ], ^, $, *, + 和 . 例如,为了写出一个文本句号,使用 "\\.",为了写出一个文本反斜线,使用 "\\\\".
使用括号包围可以得到命名子模式,如 (subpatt),那么它们就成为编码子模式. 给定的子模式的数目等于从模式的开头计算开放括号数. 可以通过使用 \\n 指代子模式(模式中的第 n 个模式),或者通过规则中的右边中的 "$n". "$0" 指的是所有匹配模式:
规则表达式 | 一般字符串模式 | 解释 |
"abc" | "abc" | 字符串 "abc" |
"." | Except["\n"] |
除了换行符以外的任意字符
|
"(?s)." | _ | 任意字符 |
"(?s).+" | __ | 一个或多个字符(贪心) |
"(?s).+?" | Shortest[__] | 一个或多个字符(非贪心) |
"(?s).*" | ___ | 零个或多个字符 |
".*" | Except["\n"]... | 零个或多个字符(除了换行符) |
"a?b" | "a" | ""~~"b"带有一个 "b" 的零个或一个 "a" (即 "b" 或 "ab") |
"[abef]" | Characters["abef"] | 任意字符 "a"、"b"、"e" 或 "f" |
"[abef]+" | Characters["abef"].. | 一个或多个字符 "a"、"b"、"e" 或 "f" |
"[a-f]" | CharacterRange["a","f"] | 在 "a" 和 "f" 范围内的任意字符 |
"[^abef]" | Except[Characters["abef"]] | 任意字符,除了 "a"、"b"、"e" 或 "f" |
"ab efg" | "ab" | "efg"匹配字符串 "ab" 或 "efg" |
"(ab ef)gh" 或 "(?:ab ef)gh" | ("ab" "ef")~~"gh" | 带有 "gh" 的 "ab" 或 "ef"(即 "abgh" 或 "efgh") |
"\\s" | WhitespaceCharacter | 任意空格字符 |
"\\s+" | Whitespace | 一个或多个空格字符 |
"(a b)\\1" | x:"a" | "b"~~x_将与 "aa" 或 "bb" 匹配 |
"\\d" | DigitCharacter | 任意数字字符 |
"\\D" | Except[DigitCharacter] | 任意非数字字符 |
"\\d+" | DigitCharacter.. | 一个或多个数字字符 |
"\\w" | WordCharacter "_" | 任意数字、字母或 "_" 字符 |
"[[:alpha:]]" | LetterCharacter | 任意字母字符 |
"[^[:alpha:]]" | Except[LetterCharacter] | 任意非字母字符 |
"^abf" 或 "\\Aabc" | StartOfString~~"abf" | 在字符串开头的字符串 "abf" |
"(?m)^abf" | StartOfLine~~"abf" | 在行开头处的字符串 "abf" |
"wxz$" 或 "wxz\\z" | "wxz"~~EndOfString | 在字符串末尾处的字符串 "wxz" |
"wxz\\Z" | "wxz"~~"\n"EndOfString | ""~~在字符串末尾或字符串末尾的换行符之前的字符串 "wxz" |
在规则表达式中的一些特殊结构在一般字符串模式中不直接可用. 这些包括 lookahead/lookbehinds 以及给定长度的重复. 它们可以通过插入一个 RegularExpression 对象,嵌入一个较大的一般字符串模式.
StringMatchQ
StringMatchQ 用来检查整个字符串是否与某个模式匹配:
StringMatchQ 是特别的,因为它允许元字符 * 和 @ 作为通配符输入(为了后面兼容的原因). * 与 Shortest[___] 等价(RegularExpression["(?s).*?"])和 @ 与 Except[CharacterRange["A","Z"]] (RegularExpression["[^A-Z]"])等价.
注意,技术上说,这里 Shortest 的出现没有任何区别,由于我们只寻找可能的匹配.
如果用户需要范围模式中子模式匹配的字符串的各部,则必须使用 StringCases.
StringFreeQ
StringContainsQ
StringStartsQ
StringEndsQ
StringCases
StringCases 是用来在字符串中寻找模式出现次数,选出子模式并且处理结果的一般目的函数.
用户也可以把字符串列表作为许多字符串有效处理的第一个变量(参见 "有效匹配的技巧" 以获得更多的讨论信息):
重叠选项
对于 StringCases,StringPosition 和 StringCount 的 Overlaps 选项处理在找到一个匹配后匹配器如何继续的问题. 它具有三个可能的设置:False,True,或 All. 对于 StringCases 和 StringCount,默认值是 False,而对于 StringPosition,默认值是 True.
StringPosition
StringCount
StringCount 返回匹配的子串数目(可以使用 StringPosition 或 StringCases)找到. 对于具有许多匹配的情况,用来存储所有子串的内存空间将成为问题,那么以上操作就是有用的:
StringReplace
StringReplace 用于替代与给定模式匹配的子串:
注意,替换不必是一个字符串. 如果结果不是一个字符串的话,返回 StringExpression:
StringReplaceList
StringReplaceList 返回字符串列表,这里单个字符串的替代以各种可能的方式进行:
StringSplit
StringSplit 对于把字符串在与模式匹配的分隔符处分成许多字符串是有用的. 默认情况下,分隔在空格符的每次运行之间进行:
这些也可以通过把 All 指定为第三个变量包含进来:
用户也可以在与位置如 StartOfLine 匹配的模式处分割. 这里在结果中保留换行符:
概况浏览
除了一般字符串模式外,Wolfram 语言可以是 Perl 或 Python 等语言的许多日常普通编程任务的强大替代. 对于熟悉 Perl 语法,以及 Perl 进行字符串操作的方式的用户,下面的概要显示如何熟悉 Wolfram 语言中相同的功能.
Perl 结构 | Wolfram 语言函数 | 解释 |
m/ .../ | StringFreeQ 或 StringCases | 把字符串与规则表达式匹配,可能提取子模式 |
s/ .../ .../ | StringReplace | 替换与规则表达式匹配的子串 |
split(...) | StringSplit | 在与规则表达式匹配的分隔符处分隔字符串 |
tr/ .../ .../ | StringReplace | 用其它字符替换字符 |
/i | IgnoreCase->True 或 "(?i)" | 与大小写无关的修饰符 |
/s | "(?s)" | 迫使 "." 匹配所有字符(包括换行符) |
/x | "(?x)" | 忽略空格键,并且在规则表达式中允许扩展注释 |
/m | "(?m)" | 多行模式 ("^" 和 "$" 匹配行的开头/末尾) |
m/.../
在 Wolfram 语言中,使用 StringCases 实现这一操作:
在 Wolfram 语言中可以使用 StringCases 实现同样功能:
s/.../.../
Perl 中 替换操作符的明显的 Wolfram 语言版本是 StringReplace:
split(...)
Perl 中的 命令与 Wolfram 语言中的 StringSplit 相似:
在模式中用来捕获括号的 ,捕获的子串被包括在结果中,可以在 Wolfram 语言中使用StringSplit 的第二个变量中的规则来实现. 与 Perl 相比较,在 Wolfram 语言中,把函数用于这些子串是容易的:
tr/.../.../
Perl 命令可以使用 Wolfram 语言 StringReplace 以及合适的规则列表模拟.
这里在 Wolfram 语言中使用 Thread 产生合适的规则:
Perl 中的字符范围在 Wolfram 语言中使用 CharacterRange 仿效:
高亮模式(Highlight Patterns)
HTML解析
下面是来自 www.google.com 的源代码:
寻找货币
这也是一个内置模式对象,对于该特殊情况为 NumberString:
在文件中寻找文本
StringExpression 与 RegularExpression 的比较
由于 Wolfram 语言语法中的字符串模式很快被转化为一个规则表达式,并且被编译和保存,所以比起直接的规则表达式语法来说,使用 Wolfram 语言语需要很小. 一个例外情况是当许多不同模式被多次使用时;在那种情况下,需要可能会变得显著一些.
条件和模式测试
如果一个模式包含 Condition(/;)或 PatternTest(?)语句,一般 Wolfram 语言计算器必须在匹配过程中调用,因此会降低速度. 如果不使用这样的结构写模式的话,通常速度会更快:
避免嵌套量词
由于在匹配中使用非确定性有限自动机算法(NFA),涉及嵌套量词(如 __ 和 patt.. 或规则表达式)的模式可以变得任意缓慢. 这样的模式经常可以被打开成更有效的版本(见 Friedl [2] 以获得更多信息.)
避免对函数的多次调用
如果用户在整个字符串长列表中寻找匹配,一次性把整个列表传给字符串函数更为有效,而不使用一些比如 Select 和 StringMatchQ 的操作(具体演示,参见更前面的字典示例). 以下示例产生 2000 个字符串的列表,每个字符串具有 10 个字符,并且搜寻以 "a" 开头并且包含 "ggg" 作为子串的字符串:
把一般表达式搜索重写为字符串搜索
由于字符串匹配算法与用来做一般表达式匹配的 Wolfram 语言算法不同(例如,字符串匹配可以假定一个有限的字母和平面结构),存在把普通表达式匹配问题转化为字符串匹配问题是有利的情况. 一个典型的情况是把符号的长列表与涉及 __ 和 ___ 多次出现的模式匹配.
Wolfram 语言中的字符串模式匹配建立于 PCRE 顶端(Perl 可兼容规则表达式)的库,作者为 Philip Hazel [1].
由于PCRE目前不支持在字符码255之外的预调的字符类,单词和字母字符类(如 WordCharacter 和 LetterCharacter)只包括 Unicode 范围在 0-255 之间的字符码. 因此,LetterCharacter 和 _?LetterQ 不给出在字符码 255 之外的等价的结果.
由于相似的 PCRE 限制,忽略大小写的匹配 (例如,使用 IgnoreCase->True)将只应用于在 Unicode 范围位于0-127之内的字符(即,普通英文字母"a"–"z" 和 "A"–"Z").
[1] Hazel, P. "PCRE—Perl Compatible Regular Expressions." 2004. www.pcre.org
[2] Friedl, J. E. F. Mastering Regular Expressions, 2nd ed. O'Reilly & Associates, 2002.