regex 正则表达式只匹配大写的“单词”,但有一些例外

ukqbszuj  于 2023-04-22  发布在  其他
关注(0)|答案(6)|浏览(128)

我有如下技术字符串:

"The thing P1 must connect to the J236 thing in the Foo position."

我想用正则表达式匹配那些只大写的单词(即这里的P1J236)。问题是,当句子是一个字母单词时,我不想匹配句子的第一个字母。
例如,在:

"A thing P1 must connect ..."

我只想要P1,而不是AP1。这样做,我知道我可能会错过一个真实的的“单词”(如"X must connect to Y"),但我可以接受它。
另外,如果句子都是大写的,我不想匹配大写的单词。
示例:

"THING P1 MUST CONNECT TO X2."

当然,理想情况下,我想在这里匹配技术单词P1X2,但由于它们被“隐藏”在全大写的句子中,而且这些技术单词没有特定的模式,这是不可能的。同样,我可以接受它,因为全大写的句子在我的文件中并不常见。
谢谢!

nwlqm0z1

nwlqm0z11#

在某种程度上,这将因您使用的RegEx的“风格”而异。以下基于.NET RegEx,它使用\b作为单词边界。在最后一个示例中,它还使用了负查找(?<!)(?!)以及非捕获括号(?:)
基本上,如果术语总是包含至少一个大写字母,后跟至少一个数字,则可以使用

\b[A-Z]+[0-9]+\b

对于全大写和数字(总数必须为2或更多):

\b[A-Z0-9]{2,}\b

对于全大写和数字,但至少以一个字母开头:

\b[A-Z][A-Z0-9]+\b

Granddaddy,返回具有大写字母和数字的任意组合的项目,但不是行首的单个字母,也不是全大写行的一部分:

(?:(?<!^)[A-Z]\b|(?<!^[A-Z0-9 ]*)\b[A-Z0-9]+\b(?![A-Z0-9 ]$))

细分:

正则表达式以(?:开始。?:表示--尽管后面的内容在括号中,但我对捕获结果不感兴趣。这称为“非捕获括号”。在这里,我使用括号是因为我使用了交替(见下文)。
在非捕获括号内,我有两个单独的子句,由管道符号|分隔。这是一种交替-就像“or”。正则表达式可以匹配第一个表达式 * 或第二个表达式 *。这里的两种情况是“这是该行的第一个单词吗”或“其他所有单词”,因为我们有排除行开头单字母单词的特殊要求。
现在,让我们看看交替中的每个表达式。
第一个表达式是:(?<!^)[A-Z]\b。这里的主子句是[A-Z]\b,它是任何一个大写字母,后跟一个单词边界,可以是标点符号,空格,换行符等。在此之前的部分是(?<!^),这是一个“负向后看”。这是一个零宽度Assert,这意味着它不会“消耗”字符作为匹配的一部分--在这里理解这一点并不重要。.NET中负向后查找的语法是(?<!x),其中 x 是在我们的主子句之前必须 not 存在的表达式。在这里,该表达式只是^,或行首,因此交替的这一侧翻译为“任何由单个大写字母组成的单词,该行首 not。”
好的,我们匹配的是一个字母,大写的单词,它们不在行的开头。我们仍然需要匹配由所有数字和大写字母组成的单词。
它由交替中第二个表达式的相对较小部分处理:\b[A-Z0-9]+\b\b表示单词边界,[A-Z0-9]+将一个或多个数字和大写字母匹配在一起。
表达式的其余部分由其他lookarounds组成。(?<!^[A-Z0-9 ]*)是另一个负lookbehind,其中表达式为^[A-Z0-9 ]*。这意味着前面的内容不能全是大写字母和数字。
第二个lookaround是(?![A-Z0-9 ]$),这是一个负的lookahead。这意味着后面的内容不能全是大写字母和数字。
因此,总的来说,我们捕获了所有大写字母和数字的单词,并从行的开头排除了单字母大写字符,并从所有大写的行中排除了所有字符。
这里至少有一个缺点,第二个交替表达式中的lookarounds独立地起作用,所以像“A P1 should connect to the J 9”这样的句子将匹配J 9,但不匹配P1,因为P1之前的所有内容都是大写的。
解决这个问题是可能的,但它几乎会使正则表达式的长度增加三倍。试图在一个正则表达式中做这么多事情是很少的,如果有的话,是公正的。你最好把工作分成多个正则表达式,或者在你选择的编程语言中组合正则表达式和标准字符串处理命令。

w3nuxt5m

w3nuxt5m2#

也许你可以先运行这个正则表达式,看看这一行是否都是大写的:

^[A-Z \d\W]+$

只有当它是像THING P1 MUST CONNECT TO X2.这样的行时才匹配
否则,您应该能够使用以下命令提取单个大写短语:

[A-Z][A-Z\d]+

应与The thing P1 must connect to the J236 thing in the Foo position.中的“P1”和“J236”匹配

kupeojn6

kupeojn63#

不要像[A-Z]或[0-9]这样的操作,而是使用\p{Lu}和\d。当然,这对于基于perl的正则表达式是有效的。这包括java。
我建议你不要做一些巨大的正则表达式。首先将文本拆分成句子。然后将其标记化(拆分成单词)。使用正则表达式检查每个标记/单词。跳过句子中的第一个标记。检查是否所有标记都是大写的,如果是,则跳过整个句子,或者在这种情况下改变正则表达式。

l2osamch

l2osamch4#

为什么需要在一个monster-regex中实现这些呢?您可以使用实际代码来实现其中的一些规则,如果以后这些需求发生变化,这样做会更容易修改。
例如:

if(/^[A-Z0-9\s]*$/)
    # sentence is all uppercase, so just fail out
    return 0;

# Carry on with matching uppercase terms
ve7v8dk2

ve7v8dk25#

我不是一个正则表达式Maven。但是试试看:

<[A-Z0-9][A-Z0-9]+>

<           start of word
[A-Z0-9]    one character
[A-Z0-9]+   and one or more of them
>           end of word

我不会为了整个大写句子的加分而尝试。呵呵

mitkmikd

mitkmikd6#

对于您建议的第一种情况,您可以用途:':blank:+[A-Z 0 -9]+:blank:+',例如:
echo“thing P1 must connect to the J236 thing in the Foo position”|grep -oE ':blank:+[A-Z0-9]+:blank:+'
在第二种情况下,也许你需要使用其他东西,而不是正则表达式,也许是一个带有技术词汇字典的脚本......
干杯,费尔南多

相关问题