0

我有一个解析文件并将它们转换为 XML 的应用程序。应用程序中的处理模块之一使用正则表达式来查找自由文本中的模式。我正在尝试识别 2 种模式,但不是很成功。

模式 1:2 个字母(不包括元音)后跟 2 个数字 (1-9),然后是 2 个字母(不包括元音),然后再定义 2 个字母(例如:WP、NL、GP、EC 等)。每个组之间可能有也可能没有空格。

例子:

BQ 12 RT WP
BQ12RTGP
BQ12RT GP

模式 2:3 个字母 (az) 后跟 3 个数字 (1-9),后跟 2 个已定义的字母(例如:WP、NL、GP、EC 等)。每个组之间可能有也可能没有空格。

例子:

ABC 123 GP
ABC123GP
ABC123 GP

这是在文本中查找特定单词的正则表达式示例:

4

4 回答 4

4

由于您显然对正则表达式没有太多经验,因此我将在这里解释很多。

首先是一点背景:正则表达式有标记和量词。标记是匹配某物的事物,例如A与拉丁大写字母 A 匹配的标记。量词通过放置在标记之后来应用于标记,并修改该标记可以连续匹配的频率,例如+是一个量词,以便前面的标记匹配至少一次,所以A+匹配A, AAAA, 或AAAAAAAAA.

有了这些,您将需要一些关于不同类型令牌的入门知识。

  1. 我们已经提到过的一个:文字字符,例如A1或其他。对于可以采用几个定义值之一的部分,您将需要它。WP将匹配WP,但没有别的。

  2. 有字符类。这些写在方括号中,包含各种字符,每个字符都可以匹配。字符类[AB]匹配 。也可以有字符范围,因此将匹配作为 ASCII 一部分的任何大写拉丁字母,将匹配从到的任何数字。A B[A-Z][1-9]19

然后我们需要一些量词:

  1. ?导致前面的标记根本不匹配或仅匹配一次,因此AB?(请记住,?仅适用于B- 直接前面的标记)将匹配AAB。如果可能,它将始终尝试匹配AB

  2. 精确的重复可以写成{5}- 即花括号中的数字。A{2}将匹配AA

好的,我们现在可以开始构建正则表达式了。

首先,我们需要一个包含没有元音字母的字符类。[A-Z]显然会包括它们,所以这还不够。但是我们可以使用多个范围:

[B-DF-HJ-NP-TV-Z]

不漂亮,但有效。一些正则表达式引擎对实际设置操作有规定,例如设置差异以使用字符类并再次排除某些字符,但现在就足够了。

但是,我们需要其中两个,因为有两个字母:

[B-DF-HJ-NP-TV-Z]{2}

然后有一个空间,也可能没有。有一个包含所有空格(包括空格和制表符)的速记字符类:\s. 我们可以使用它,除非严格要求只能出现空格:\s?. 为了增加健壮性,我们还可以使用\s*which 将匹配任意数量的空格,即使没有空格也可以不匹配。

然后我们需要来自 : 的数字,1实际上9还有[1-9]两个数字:[1-9]{2}。到目前为止,我们有以下内容:

[B-DF-HJ-NP-TV-Z]{2}\s*[1-9]{2}

然后我们需要两个不带元音的字母,再带空格或不带空格:

[B-DF-HJ-NP-TV-Z]{2}\s*[1-9]{2}\s*[B-DF-HJ-NP-TV-Z]{2}\s*

在那之后,有一部分是可能的几个定义的选项之一。这些可以用竖线交替书写|。我们首先需要一个用括号编写的组,就像在数学中一样,以限制交替的优先级(再次,就像在数学中一样)。在它们里面,我们只列出所有可能的选项,用 分隔|

(WP|NL|GP|EC|etc.)

这就像字符类,只是它将匹配多个字符(但仍然只有一个选项)。

把它们放在一起,我们有

[B-DF-HJ-NP-TV-Z]{2}\s*[1-9]{2}\s*[B-DF-HJ-NP-TV-Z]{2}\s*(WP|NL|GP|EC|etc.)

然后是一件小事。即使周围有字符,它也会匹配,因为大多数引擎中的正则表达式默认匹配子字符串。我们从来没有说过我们上面匹配的内容需要是一个单一的“单词”,可以这么说,它可能是我们在khdgdfgergBQ12RTGPrteryefg某个地方找到的。为了防止某些断言本身不会匹配任何字符,而是将匹配项与特定位置联系起来。其中一个很方便的是,它将匹配字符 from (在实践中完全无用的速记字符类,包括字母、数字和下划线)和字符 not from\b之间存在边界的任何地方。对于快速和肮脏的黑客攻击足以确保我们匹配单词的开头或结尾,例如\w\w\b\bfoo\b将匹配fooina foo b但不在foobar. 有些选项更健壮,但编写时间也更长。所以我们可以使用以下对于某些目的应该足够好的:

\b[B-DF-HJ-NP-TV-Z]{2}\s*[1-9]{2}\s*[B-DF-HJ-NP-TV-Z]{2}\s*(WP|NL|GP|EC|etc.)\b

不过,我现在将第二个模式的构建留给您。你现在应该足够了解自己来做这件事了。

顺便说一句,一个非常好的学习正则表达式的网站是regular-expressions.info。事情的解释比我做的更好,它对于学习和作为参考同样有用

于 2013-03-07T09:28:59.563 回答
0

你可以用这个正则表达式来做到这一点

^(?!.*[aeiou].*(WP|NL|GP|EC))[a-zA-Z]{2}\s*\d{2}\s*[a-zA-Z]{2}\s*(WP|NL|GP|EC)$
于 2013-03-07T09:17:58.370 回答
0

你可以尝试这样的事情:

模式1:

[^\W\d_.AEIOUYaeiouy]{2}\s*\d{2}\s*[^\W\d_.AEIOUYaeiouy]{2}\s*(?:WP|NL|GP|EC)

非常简单,使用反转组,因为它比 短[bcdfghjklmnpqrstvwxzBCDFGHJKLMPQRSTVWXZ],如果你可以让它不区分大小写或者知道它总是大写,你可以让它更短。添加更多的 2 个字母“单词”可以通过添加|XX到最后一部分(括号内)来完成。

模式2:

[A-Za-z]{3}\s*\d{3}\s*(?:WP|NL|GP|EC)

根据您使用的语言,您可能需要更改一些内容。

于 2013-03-07T09:08:08.360 回答
0

假设字母必须是大写的:

模式一:[BCDFGHJ-NP-TV-Z]{2}\s*[1-9]{2}\s*[BCDFGHJ-NP-TV-Z]{2}\s*(?:WP|NL|GP|EC)

模式二:[A-Z]{3}\s*[1-9]{3}\s*(?:WP|NL|GP|EC)

\b如果您要求字符串以非单词字符或字符串的开头/结尾为边界,您可能还需要考虑添加到每个字符串的开头和结尾。

于 2013-03-07T09:10:00.687 回答