首页 > 解决方案 > Java:如何使用高级字符串 replaceAll Regex w/ 和 w/out Lookahead/Lookbehind

问题描述

我试图只接受单词中间有或没有连字符的常规单词,或者单词中间或末尾的撇号。因此,任何数字字符串或具有任何其他特殊字符的字符串都将替换为空格。也不需要考虑前面的空格,因为这些字符串将从文件中读入并且已经使用空格分隔。

即“0”、“-hi”、“hi-”和“'hello”都将被拒绝。

但是,“apple”、“Ben's”、“Ben'”和“well-respected”将被接受。

我试图用 Java 的 String replaceAll 功能来解决这个问题。我想知道如何使用“简单”正则表达式来做到这一点,以及如何利用更高级的后向/前瞻来实现这一目标。

到目前为止,关于 RegEx,这是我尝试过的:

String tempString;
tempString = tempString.replaceAll("^([a-zA-Z]+(-)?[a-zA-Z]+)"," ");
tempString = tempString.replaceAll("^([a-zA-Z]+(')?[a-zA-Z]*)"," ");
//Basically if it does not meet this condition, replace w/ whitespace

截至目前,正则表达式的语法甚至都不正确。针对上面相关的“未接受”词测试这两个中的任何一个都不会用“”替换它们。最重要的是,我需要将这两个 RegEx 合并为一个,以实现适当的整体功能。

在类似的说明中,据我所知,我可以利用前瞻/后瞻来实现所需的结果。但是,在阅读了该过程之后,我对将插入 replaceAll 函数的语法感到困惑。

所以,我的两个问题如下:

  1. 我可以在 RegEx 的语法中更改哪些内容以在一个 replaceAll 函数调用中同时检查连字符和撇号?
  2. 我如何利用前瞻/后瞻来实现相同的目标?

请注意,我不是在寻找其他解决方案,因为我正在努力更好地理解 RegEx。这也是我在这里的第一个问题,因此对任何格式问题或其他愚蠢的事情表示歉意。

谢谢!

标签: javaregexregex-lookarounds

解决方案


这个正则表达式应该有效。但是我们必须将输入文件拆分为单词,然后进行正则表达式。因为 String.replaceAll 搜索序列继续。例如'-apple',replaceAll 将总是跳过'-',然后匹配'apple'。

legal chars + ( (- or' ) and legal chars )``+ ( (- or') and legal chars ) + ...

@Test
public void test() {
    Pattern pattern = Pattern.compile("([\\w]*[a-zA-Z][\\w]*)([-'][\\w]*[a-zA-Z][\\w]*)*");

    Matcher m = pattern.matcher("0");
    Assert.assertFalse( m.matches());
    m = pattern.matcher("apple");
    Assert.assertTrue( m.matches());
    m = pattern.matcher("apple-");
    Assert.assertFalse( m.matches());
    m = pattern.matcher("-apple");
    Assert.assertFalse( m.matches());
    m = pattern.matcher("apple-a0");
    Assert.assertTrue( m.matches());
    m = pattern.matcher("Tom-Jerry's");
    Assert.assertTrue( m.matches());
}

推荐阅读