在某种程度上,这会因您使用的 RegEx 的“风味”而异。以下基于 .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 ]$))
分解:
正则表达式以(?:
. 表示 - 尽管后面的?:
内容在括号中,但我对捕获结果不感兴趣。这称为“非捕获括号”。在这里,我使用的是括号,因为我使用的是交替(见下文)。
在非捕获括号内,我有两个由管道符号分隔的单独子句|
。这是交替——就像一个“或”。正则表达式可以匹配第一个表达式或第二个表达式。这里的两种情况是“is this the first word of the line”或“everything else”,因为我们有排除行首单字母词的特殊要求。
现在,让我们看看交替中的每个表达式。
第一个表达式是:(?<!^)[A-Z]\b
。这里的主要子句是[A-Z]\b
,它是任何一个大写字母后跟一个单词边界,可以是标点符号、空格、换行符等。在这之前的部分是(?<!^)
,这是一个“负向后看”。这是一个零宽度断言,这意味着它不会“消耗”字符作为匹配的一部分——在这里理解这一点并不重要。.NET 中否定向后查找的语法是(?<!x)
,其中x是在我们的主子句之前不得存在的表达式。在这里,该表达式是简单^
的,或行首,因此交替的这一侧翻译为“任何由单个大写字母组成的不在行首的单词”。
好的,所以我们正在匹配不在行首的单字母大写单词。我们仍然需要匹配由所有数字和大写字母组成的单词。
这由交替中第二个表达式的相对较小部分处理:\b[A-Z0-9]+\b
。\b
s 代表单词边界,将一个[A-Z0-9]+
或多个数字和大写字母匹配在一起。
表达式的其余部分由其他环视组成。(?<!^[A-Z0-9 ]*)
是另一个否定的lookbehind,表达式为^[A-Z0-9 ]*
。这意味着前面的内容不能全部是大写字母和数字。
第二个环视是(?![A-Z0-9 ]$)
,这是一个负前瞻。这意味着后面的内容不能全部是大写字母和数字。
因此,总的来说,我们正在捕获所有大写字母和数字的单词,并且从行首排除一个字母的大写字符以及所有大写行中的所有内容。
这里至少有一个弱点,第二个替换表达式中的环视是独立的,所以像“A P1 应该连接到 J9”这样的句子将匹配 J9,但不匹配 P1,因为 P1 之前的所有内容都是大写的。
可以解决这个问题,但它几乎会使正则表达式的长度增加三倍。尝试在单个正则表达式中做这么多事情很少,如果有的话,是合理的。您最好将工作分解为多个正则表达式或您选择的编程语言中的正则表达式和标准字符串处理命令的组合。