正则表达式以在自由文本中查找字符模式

时间:2013-03-07 08:46:39

标签: regex

我有一个解析文件并将其转换为XML的应用程序。应用程序中的一个处理模块使用正则表达式来查找自由文本中的模式。我试图确定2种模式但不是很成功。

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

示例:

BQ 12 RT WP
BQ12RTGP
BQ12RT GP

模式2:3个字母(a-z),后跟3个数字(1-9),接着是另外2个定义的字母(例如:WP,NL,GP,EC等)。每个组之间可能有也可能没有空格。

示例:

ABC 123 GP
ABC123GP
ABC123 GP

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

4 个答案:

答案 0 :(得分:4)

由于你对正则表达式没有多少经验,我将在这里解释很多。

首先是一个小背景:正则表达式有令牌和量词。令牌是匹配某些东西的东西,例如A是与拉丁大写字母A匹配的标记。量词通过放置在它们之后应用于标记,并修改该标记在一行中可以匹配的频率,例如: +是一个量词,因此前面的代码至少匹配一次,因此A+匹配AAAAAAAAAAAAAA

在此之后,您将需要一些关于不同类型令牌的入门知识。

  1. 我们已经提到的一个:文字字符,例如A1或其他字符。对于可以采用几个定义值之一的零件,您需要这个。 WP将匹配WP,但不会匹配。

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

  3. 然后我们需要一些量词:

    1. ?导致前一个令牌完全匹配或完全匹配,因此AB?(请记住,?仅适用于B - 前面的标记)将匹配AAB。如果可能,它将始终尝试匹配AB

    2. 可以使用{5}写出精确重复 - 也就是花括号中的数字。 A{2}将与AA匹配。

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

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

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

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

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

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

      然后有一个空间或者可能没有。有一个速记字符类,包括所有空格(包括空格和制表符):\s。我们可以使用它,除非严格要求只显示空格:\s?。为了增加稳健性,我们还可以使用\s*来匹配任意数量的空格,如果没有空格则不使用。

      然后我们需要19[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。为了防止某些断言本身不匹配任何字符,但将匹配绑定到特定位置。其中一个方便的是\b,它将匹配\w(一个在实践中完全无用的速记字符类,包括字母,数字和下划线)的字符之间存在边界的任何地方。和一个不是来自\w的角色。对于快速而肮脏的黑客行为\b足以确保我们匹配单词的开头或结尾,例如\bfoo\b将与foo中的a 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 。有些选项更强大,但写入时间也更长。因此,我们可以使用以下内容,这些内容应该足够用于某些目的:

      {{1}}

      不过,我现在将把第二种模式的构造留给你。你现在应该自己知道了。

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

答案 1 :(得分:0)

您可以尝试这样的事情:

<强>样式1:

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

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

<强> PATTERN2:

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

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

答案 2 :(得分:0)

假设这些字母必须是大写的:

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

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

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

答案 3 :(得分:0)

你可以使用这个正则表达式

^(?!.*[aeiou].*(WP|NL|GP|EC))[a-zA-Z]{2}\s*\d{2}\s*[a-zA-Z]{2}\s*(WP|NL|GP|EC)$