regex 与固定宽度负向后查找相关的正则表达式的特定问题

1hdlvixo  于 2023-10-22  发布在  其他
关注(0)|答案(4)|浏览(131)

我正在写一个正则表达式(如果这很重要的话,在Java中使用),它试图匹配$后面的数字(可以是浮点数)(允许$和数字之间有空格),但前提是它前面的单词不是单词'LOST'。
如果有多个可能的匹配项,则应返回第一个数字。
为简单起见,假设所有字符都是大写。
例如,在下面的句子中:“I PAID $10.12 FOR THE BEER”,10.12将匹配。对于句子“I LOST $11.34 IN THE GAME”,将不会有匹配。对于“我在游戏中输掉了11.34美元,但为啤酒支付了10.12美元”,仍然匹配10.12美元。
我得到的正则表达式是

.*?(?<!LOST )[$]\s*(?<NUMBER>[0-9]*[.]?[0-9]*).*

我的正则表达式通常工作得很好,尽管我想知道是否有更简单的方法来编写它/如果我错过了任何角落的情况。一个小问题是,如果LOST和$之间有一个以上的空格,我仍然不想匹配,但目前我的正则表达式将匹配。不幸的是,负向后看必须具有固定的宽度。
说明:为了澄清,当我说“紧接在它前面的单词不是单词'LOST'”时,我的意思是在'$'之前不能有'LOST\s'。这意味着'LOST $123'和'LOST $123'都不应该匹配123,而是'LOST!123美元“可以匹配123。理由是货币不应该被LOST直接“作用”;如果在LOST和$之间有除\s以外的任何东西,那么LOST很有可能不会直接“作用于”该货币。

jyztefdp

jyztefdp1#

假设"LOST"和美元符号之间可能有1到99个空格。我还假设这个数字有两位小数,并且没有逗号作为千位分隔符。然后可以尝试将字符串与正则表达式进行匹配

(?<!\bLOST\s{1,99})\$(?<NUMBER>(?:0|[1-9]\d*)\.\d{2})\b

如果存在匹配项,则名为NUMBER的捕获组将包含感兴趣的美元金额。
Demo
将光标悬停在链接处的正则表达式上,以获取表达式中每个元素的说明。
另一种方法是尝试匹配正则表达式

\bLOST\s+\$(?:0|[1-9]\d*)\.\d{2}\b|\$(?<NUMBER>(?:0|[1-9]\d*)\.\d{2})\b

Demo
在这种情况下,不要注意没有捕获的匹配;只发送给接收到的,在这种情况下,捕获组NUMBER将包含感兴趣的货币值。这里

\bLOST\s+\$(?:0|[1-9]\d*)\.\d{2}\b

匹配,但不捕获,值前面是“LOST”,后面是一个或多个空格,后面是美元符号。有人可能会说它吞噬了这样的子串。

qv7cva1a

qv7cva1a2#

blhsing's answer的启发,我提出了这个正则表达式,它可能看起来更干净,并且具有更广泛的边缘情况覆盖:

(?:^|(?<!LOST)\b)\W*\$(?<NUMBER>\d+(?:\.\d+)?)

因为Java不能有非固定宽度的lookbehind。你向后看的位置很关键。
1.由于您不希望货币为LOST之前的单词,因此可以先匹配单词边界:

\b

1.然后,您需要确保该字不是LOST

(?<!LOST)\b

1.之后,将您的货币匹配放在它后面,前面是可选的非单词字符:

(?<!LOST)\b\W*\$(?<NUMBER>\d+(?:\.\d+)?)

1.然后,添加一些边缘情况,例如以货币开头的字符串:

(?:^|(?<!LOST)\b)\W*\$(?<NUMBER>\d+(?:\.\d+)?)

查看test cases

vof42yt1

vof42yt13#

由于Java中的lookbehind模式必须具有固定的宽度,因此可以通过使用负lookahead模式来排除单词LOST,从而允许可变数量的空格。还包括交替模式中的^行的开头,以防在那里发生匹配:

(?:^|(?!LOST\b)\b\w+\s*)\$\s*(?<NUMBER>\d+\.\d+)

演示:https://regex101.com/r/4pqyc0/7

olqngx59

olqngx594#

我不会在这里使用lookbehind,而是一个捕获组:

String input = "I LOST $11.34 IN THE GAME AND PAID $10.12 FOR THE BEER";
String pattern = "\\bLOST \\$?(\\d+(?:\\.\\d+)?)";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(input);
if (m.find()) {
    System.out.println(m.group(1));  // 11.34
}

相关问题