在一定程度上,这将取决于您使用的正则表达式“风格”。以下基于.NET RegEx,它使用
\b
表示单词边界。在最后一个示例中,它还使用负向先行断言
(?<!)
和
(?!)
以及非捕获括号
(?:)
。
基本上,如果术语始终包含至少一个大写字母后跟至少一个数字,您可以使用:
\b[A-Z]+[0-9]+\b
对于所有大写字母和数字(总数必须为2或更多):
\b[A-Z0-9]{2,}\b
针对全大写字母和数字,但是起始至少要有一个字母:
\b[A-Z][A-Z0-9]+\b
这个正则表达式的作用是匹配包含任意大写字母和数字组合的项,但不匹配行首的单个字母,也不匹配全部为大写字母的行中的项:
(?:(?<!^)[A-Z]\b|(?<!^[A-Z0-9 ]*)\b[A-Z0-9]+\b(?![A-Z0-9 ]$))
细节解析:
这个正则表达式以(?:
开始。 ?:
表示虽然后面内容被放在了括号里,但我不想捕获结果。这称为“非捕获性括号”。 在这里,我使用括号是因为我使用了"或"(见下文)。
在非捕获性括号内,我有两个由管道符号|
分隔的单独子句。 这就是“交替”--类似于“或者”的意思。 正则表达式可以匹配第一个表达式或第二个表达式。这两种情况是“这是行的第一个单词”或“其他所有情况”,因为我们有一个特殊要求,即在行开头排除一个字母的单词。
现在,让我们看看交替中的每个表达式。
第一个表达式是:(?<!^)[A-Z]\b
。 这里的主要子句是[A-Z]\b
,它是任何一个大写字母后跟一个单词边界,可以是标点符号、空格、换行符等。在那之前的部分是(?<!^)
,这是一个"负向后查找"。这是一个零宽断言,这意味着它不会“消耗”字符作为匹配的一部分--在这里并不重要。.NET中负向后查找的语法是(?<!x)
,其中x是必须不存在于主子句之前的表达式。 这里的表达式只是^
,即行首,因此交替边上的内容翻译为“任何由单个大写字母组成的单词,而且该单词不再行开头。”
好的,所以我们正在匹配不在行首的大小写字母单词。 我们仍然需要匹配由所有数字和大写字母组成的单词。
这由交替中第二个表达式的相对较小部分处理:\b[A-Z0-9]+\b
。 \b
代表单词边界,而[A-Z0-9]+
匹配一个或多个数字和大写字母放在一起。
表达式的其余部分由其他查找构成。 (?<!^[A-Z0-9 ]*)
是另一个负向后查找,其中表达式为^[A-Z0-9 ]*
。 这表示前面的内容不能都是大写字母和数字。
第二个查找是(?![A-Z0-9 ]$)
,它是一个负向前瞻。这表示后面的内容不能全部是大写字母和数字。
所以总体来说,我们捕获由所有大写字母和数字组成的单词,并从行开头排除一个字母的单词和全部大写字母的行中的所有内容。
这里至少有一个弱点,在交替表达式的第二部分中的查找是独立的,因此像“A P1 should connect to the J9”这样的语句将匹配J9,但不会匹配P1,因为P1之前的所有内容都是大写的。
可以解决这个问题,但它几乎会使正则
[A-Z]
这样的7位文字。那很像RADIX-50,并且在过去几十年写的代码中没有用武之地。使用适用于任何文本的内容。至少这意味着在您的正则表达式语言和环境中使用与\w
或[[:alpha:]]
或\pL
或\p{Alphabetic}
相关的东西。实际上,实现差异如此之大,以至于其中一些在某些平台上可能是合法和正确的,但在其他平台上则是合法而错误的。 - tchrist