【问题标题】:How to make a regular expression for this seemingly simple case?如何为这个看似简单的案例制作正则表达式?
【发布时间】:2021-10-20 15:39:45
【问题描述】:

是否可以编写一个与 String replaceAll() 一起使用的正则表达式,以从行尾删除零个或多个空格并用单个句点 (.) 替换它们。

例如,regex 将使这些(非详尽的)测试用例通过:

String regex = "????";
assertEquals("foo.", "foo".replaceAll(regex, "."));
assertEquals("foo.", "foo ".replaceAll(regex, "."));
assertEquals("foo.", "foo  ".replaceAll(regex, "."));
assertEquals(" foo.", " foo  ".replaceAll(regex, "."));

我知道我可以用replaceFirst(" *$", ".") 做到这一点,但我想知道它是否可以用replaceAll() 做到。

更新添加: 问题的原因是我正在编写一个数据驱动的转换链,它只有replacereplaceAll 作为允许的转换。我可以通过两个replaceAll 转换来做到这一点。我只是想知道是否有可能做到这一点。

【问题讨论】:

    标签: java regex


    【解决方案1】:

    您可以使用基于交替的模式来匹配字符串末尾的一个或多个空格,或者匹配之前没有空格的字符串结尾:

     +$|$(?<! )
    \h+$|$(?<!\h)
    \s+$|$(?<!\s)
    

    请参阅regex demo\h 匹配水平空格,\s 匹配任何空格字符。

    另外,$ 可以替换为 \z 以匹配字符串的最后。

    Java demo

    String regex = "\\s+\\z|\\z(?<!\\s)";
    System.out.println("foo.".equals("foo".replaceAll(regex, ".")));
    System.out.println("foo.".equals("foo ".replaceAll(regex, ".")));
    System.out.println("foo.".equals("foo  ".replaceAll(regex, ".")));
    System.out.println(" foo.".equals(" foo  ".replaceAll(regex, ".")));
    

    所有测试用例都显示true 作为输出。

    【讨论】:

    • 啊,我明白了,对第二种选择使用否定的后视来防止双重匹配。
    • 关于使用\z 而不是$ 的好处。
    【解决方案2】:

    您可以确保您的“空格列表”前面有“非空格”:

    (?<=\S)\s*$
    

    也覆盖空字符串:

    (?<=\S|^)\s*$
    

    【讨论】:

    • 这不适用于空字符串。我知道那不是我的测试用例之一!
    • @ᴇʟᴇvᴀтᴇ 嗯,确实,我认为空字符串不应该变成一个点,如果需要,您仍然可以(?&lt;=\S|^),更新。
    • 这行得通,我已经投了赞成票,但后视方法略短。
    【解决方案3】:
    (?<!\s)\s*$
    

    您可以确保您的“空格列表”前面没有“空格”。

    而不是: 你可以确保你的“空格列表”前面是“不是空格”

    因为(?&lt;=\S)(作为字符集)不匹配空字符串,但(?&lt;!\s) 匹配。

    Regex101 Demo

    【讨论】:

    • 当最后一个非空格字符已经是句点时,添加最后一个句点是否正确?
    猜你喜欢
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 2015-01-12
    • 2011-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多