正则表达式
\b(\w*)[[à-ü]|[À-Ü]]\b
查找以西班牙语波浪号(又名重音符号)结尾的单词。例如,在“Tengo algún Cafe”中,它匹配 algún
和 café
。
我想修改它,以便它捕获当前匹配项前面的单词。例如,在“El mandatario celebró en sus redes”中,它应该匹配
mandatario
。我对此正则表达式的 Java 实现特别感兴趣。
我尝试使用捕获组如下:
Pattern pattern = Pattern.compile("\\b( \\w* )[[à-ü]|[À-Ü]]\\b");
然后提取
String precedingWord = matcher.group(1);
。然而,这并没有奏效。
例如,在“Tengo algún咖啡馆”中,它匹配algún和café。
不,没有。该正则表达式有太多错误,从哪里开始?
\b
的意思\b
在基本模式下是 ascii 绑定的。所以,你会发现这种疯狂:
Pattern p = Pattern.compile("\\balgú\\b");
System.out.println(p.matcher("algún").find());
这会打印...
true
。这是疯狂的,因为它应该打印false
。毕竟,我们的输入字符串中的 ú
之后没有“断词”。事实上,用普通的旧 ascii u
替换它,你就会得到预期的 false
。
Pattern 类中对此的记录很差。正在发生的事情是,模式类试图与过时的仅 ascii 概念兼容,尽管 java 完全不是那样。因此,ú 被视为“不是单词字符”,因为它不在 a-z 范围内。我们需要告诉正则表达式不要做愚蠢的事情,我们用
(?U)
来打开“unicode 模式”。那么一切都好:
Pattern p = Pattern.compile("(?U)\\balgú\\b");
System.out.println(p.matcher("algún").find());
好吧,最后,
false
。这就是一个开始。
你需要在里面塞另一个
\w*
。而且你不需要括号。
这个:
[[à-ü]|[À-Ü]]
是官样文章。在
[]
内,大多数标准正则表达式规则都不适用。 -
具有特殊含义,除非它位于开头或结尾(在 []
之外不正确,其中 -
仅表示 -
)。 .
仅表示点(在[]
之外表示“任何字符”),+
仅表示+等等。特别是 |
只是表示 bar:
Pattern p = Pattern.compile("H[e|a]llo");
System.out.println(p.matcher("Hello").matches());
System.out.println(p.matcher("Hallo").matches());
System.out.println(p.matcher("H|llo").matches());
打印
true
... 3 次。并集(如“a 或 b”)在字符类中自动发生,如果需要交集,则需要 &&
(在 char 类中的特殊含义)。所以,你只想:
[à-üÀ-Ü]
除非你不想要那样。 unicode表中à和ü之间有一堆字符。例如,÷ 和 ø。当然 ÷ 不是您想要捕获的内容。最好明确地将它们全部列出来。
查找带有西班牙语波浪号(又名重音符号)的单词
好吧,那么,那就只是
ñ
然后:将 [à-ü]|[À-Ü]]
替换为 ñ
。或者,如果您确实想捕获 ú,例如 [ñúíáé]
- 将它们列出来。依赖 unicode 范围是自找麻烦。可能会出现一些问题,例如您无意中意外包含 ÷,并且正则表达式不建议这样做。
您可以使用
(?i)
标志来打开不区分大小写模式。
我们在:
Pattern p = Pattern.compile("(?Ui)\\b\\w*[ñáúíé]\\w*\\b");
它将匹配任何包含至少一个重音字符的单词。
您为此使用正向前瞻:
Pattern p = Pattern.compile("(?Ui)\\b\\w+\\b(?=\\s+\\w*[ñáúíé]\\w*\\b)");
Matcher m = p.matcher("Tengo algún café");
while (m.find()) System.out.println("Found: " + m.group(0));
注意包含
\\s+
- 我们需要在某处消耗 Tengo 和 algún 之间的空间。正向前瞻要求括号中的内容存在,但不会消耗它。