指南- 正则表达式

这里是一个短小的指南, 意在解开 StringRegExp() 函数的奥秘.

StringRegExp( "字符串", "正则表达式" [, 标志 ] )

"字符串" = 用于搜索匹配项的字符串.


"正则表达式" = 某些关键字组成的字符串, 可以让该函数知道该字符串中有您要匹配的字符.
匹配状态可能是:没有, 可能有, 部分匹配或不匹配.


"标志" [可选参数] = 如果“正则表达式”发现你的 "字符串" 中有指定的字符串后,
你可以指定是返回第一个匹配, 还是返回所有匹配.

基本概念

你可能已经理解, "正则表达式" 的书写是调用 StringRegExp()(以下将这个函数缩写为:SRE)惟一困难的部分.

"正则表达式" 是一个信息串, 用来告诉函数需要匹配那些字符.

要找特定的字符有可以不同的方法: 如果你想查找字符串"test", 这应该是很简单的. 您告诉 SRE 先搜索 "t".

如果能找到, 则假定是匹配的, 而"正则表达式" 的另外部分则证明有什么发现是不匹配的.

因此, 如果 SRE 的下一个查找是 “e”, 则它仍然是一个匹配.

又例如 SRE 的下一个查找是 "x". SRE 立即知道它有没有找到匹配, 因为你提供的"字符串"的第三个字符是 "s".
 

示例 1

MsgBox(0, "SRE 示例 1 的结果", StringRegExp("text", 'test'))

在这个例子中, 消息框应该返回 "0", 表示正则表达式 "test" 没有在字符串 "text" 找到匹配.

我(作者,下同)知道这看起来很简单, 但现在你知道它为什么没有被发现吗?.

指定正则表达式下一个方法是使用一个置位 ("[ ... ]"). 你可以把这个置位看成逻辑函数 "OR".

让我们使用前面的示例. 我们来查找字符串 "test" 或 "text".

我开始寻找一种正则表达式, 让 SRE 会认为: 要匹配的第一个字符是 "t", 然后是 "e", 这对于想要匹配的两个字符串是相同的.

现在, 我们要匹配 "s" OR(或) "x", 我们使用一个置位作为替换: "[sx]" 表示允许匹配 "s" 或 "x". 然后是最后一个字母 "t" 了.

示例 2

MsgBox(0, "SRE 示例 2 的结果", StringRegExp("text", 'te[sx]t'))
MsgBox(0, "SRE 示例 2 的结果", StringRegExp("test", 'te[sx]t'))

这两个结果都应该返回 "1", 因为这时的正则表达式都匹配"test" 与 "text".

你也也用指定次数的方式匹配每个字符, 使用"{匹配的次数}"或指定一个范围 "{最小,最大}".

下面的第一个例子是多余的, 但显示我想要说明的意思:

示例 3

MsgBox(0, "SRE 示例 3 的结果", StringRegExp("text", 't{1}e{1}[sx]{1}t{1}'))
MsgBox(0, "SRE 示例 3 的结果", StringRegExp("aaaabbbbcccc", 'b{4}'))

较复杂的概念

你可能在想:"这个 StringInStr() 函数不是很有趣吗?". 好吧, 使用一个值为 0 的 "标志".

大部份时间你是对的. 但 SRE 不止于此,它要强大得多.

随着你使用 SRE 越来越多时,你会发现找寻可用的正则表达式结构却越来越少.

你想要在正则表达式中指定每个具体字符的可用方法也越来越少.

例如, 一个游戏的纪录日志有一行: "Gnarly Monster hits you for 18 damage."(多疤怪物对您有 18 次打击.")

假定你想要知道多疤怪物打击你的次数. 好吧, 你不能使用 StringInStr(), 因为你不是要找寻 "18", 您应该查找 "????", 这里的 “?” 允许任意数字.

下面看我如何组合这个正则表达式. 告诉你怎么做和如何查找你想要寻找的:
1 ) 你应该知道, 它永远包含的只是数字.
2 ) 你应该知道, 它有时会是 2 个字符长度.
2a) 你应该知道, 游戏中怪物能做的最大伤害值是 999.
2b) 你应该知道, 游戏中怪物能做的最低伤害值是 0.
3 ) 你应该知道, 它的长度总是在 1 到 3 个字符之间.
4 ) 你应该知道, 字符串中没有其它数字

此时, 我想要介绍值为 1 的 标志和分组符号"()".

标志 "1" 能让 SRE 不仅匹配您的正则表达式, 而且还返回一个数组, 同时捕捉数组元素组成的“组”字符.

我没有离开本节指南离题太远吧!举这个例子:

示例 4

$asResult = StringRegExp("This is a test example", '(test)', 1)
If @error == 0 Then
    MsgBox(0, "SRE 示例 4 的结果", $asResult[0])
EndIf
$asResult = StringRegExp("This is a test example", '(te)(st)', 1)
If @error == 0 Then
    MsgBox(0, "SRE 示例 4 的结果", $asResult[0] & "," & $asResult[1])
EndIf

 

首先, 正则表达式必须匹配字符串 的某些字符串. 如果是的话, 然后告诉 SRE "捕捉"部分字符 ("()"), 并储存在返回数组中.

您可以使用多种捕捉,这表现在示例4的第二项代码中

好了, 回到多疤怪物游戏. 现在我们知道了该如何“捕捉”文字, 让我们构建我们的正则表达式:

既然你知道你所要查找的是数字, 有 3 种可以指定“匹配任意数字” 的方法: "[:digit:]", "[0-9]", 与 "\d".

第一个或许是最容易理解的. 有一些类 (digit, alnum, space, 等等. 相关信息查看帮助文件中 “StringRegExp” 的完整列表) 你可以使用指定的字符集, 其中之一就是“digit”.

"[0-9]"只是规定了数字的范围从 0 到 9.

"\d"仅仅是一个特殊字符, 它意味着前两个相同.

3 个方法之间没有差别, 并且所有的 SRE 通常至少有一对方法可以构建任何的正则表达式.

因为首先我们知道,我们想捕捉的是数字, 我们用圆括号 "(" 开始.

下一步, 我们要捕捉的数字长度介于1到3个字符之间, 并且全部是数字, 所以我们的正则表达式现在看起来像 "([0-9]{1,3}".

最后我们以反圆括号 ")" 结束我们的组: "([0-9]{1,3})". 让我们试试:

示例 5

$asResult = StringRegExp("Gnarly Monster hits you for 18 damage.", _
                               '([0-9]{1,3})', 1)
If @error == 0 Then
    MsgBox(0, "SRE 示例 5 的结果", $asResult[0])
EndIf

 

你去哪里了? 消息框现在正确显示了 "18".

下一步, 我们需要包括非捕捉组. 你可以使用 "(?:" 而不是 "(".

比方说, 您的日志说: "You deflect 36 of Gnarly Monster's 279 damage."

现在如果你在这里运行 SRE 示例 5, 你将会发现返回的是 "36" 而不是 "279".

现在我想在这里做的就是确定那些数字有些什么不同.

我们看第二个数字279,它后面跟随一个空格, 然后才是单词"damage".

我们可以只修改前面的正则表达式为 "([0-9]{1,3} damage)",

但是, 如果我们的脚本只是寻找 "damage" 的总数,并且不知道 " damage" 何时结束?

此时, 您可以使用非捕获组, 以实现这一目标.

示例 6

$asResult = StringRegExp("You deflect 36 of Gnarly Monster's 279 damage.", '([0-9]{1,3})(?: damage)', 1)
If @error == 0 Then
    MsgBox(0, "SRE 示例 6 的结果", $asResult[0])
EndIf

 

这篇指南可能太长了, 但主要是我想奠定个基础. 要了解正则表达式如何工作, 主要看 SRE 如何“认为” .几件事要记住:
- 请记住正则表达式每次传送一个字符
- StringRegExp() 函数在找到正则表达式的第一个字符后, 那么您的工作就是提供足够的证据“证明”它是否是真正的匹配. 示例6就很好的显示了这一点.
- 记住 [ ... ] "OR"的用法 ([xyz] 匹配一个 "x", 一个 "y", 或一个 "z")

如果您还有任何其他问题, 首先请阅读帮助文件的“StringRegExp”! 它详细说明了 SRE 的所有细节和语法. 尤其是 "重复字符" 区段.

它能通过为范围替换特定的字符, 使您的 "表达式" 更容易阅读. 例如: "*" 相当于 {0,} 或从 0 到任意数量的字符

祝你好运, 正则表达式可以大大减少您的代码长度, 而且使稍后的修改更容易. 欢迎校正和反馈!

资源


Wikipedia Article - Regular Expressions - 感谢 blindwig.

The 30 Minute Regex Tutorial - by Jim Hollenhorst.


GUI StringRegExp() 测试各类正则表达式 - 感谢 steve8tch. 荣誉修改: w0uter

 

维基百科 - 正则表达式 - 感谢 me.呵呵(这个是中文的)

pconline.com.cn - 正则表达式 (中文)

 

 

感谢 neogia 制作这个指南.

 

provider with jb51.net (unicode)