【问题标题】:java regex tricky patternjava正则表达式棘手的模式
【发布时间】:2011-10-02 11:35:11
【问题描述】:

我被一个正则表达式困住了一段时间:

  • 用这个分割我的句子:“[\W+]”
  • 但如果它找到这样的词:“aaa-aa”(不是“aaa - aa”或“aaa--aaa-aa”),则该词不是拆分,而是整个词。

    基本上,我想为每个单词拆分一个句子,但还要考虑“aaa-aa”是一个单词。我通过创建两个单独的函数成功地做到了这一点,一个用于与 \w 分割,另一个用于查找诸如“aaa-aa”之类的单词。最后,我将两者相加,并减去每个复合词。

    例如,句子:

    “你好,我叫理查德”

    首先我收集{你好,我的名字,是,理查德} 然后我收集{我的名字} 然后我将 {my-name} 添加到 {Hello, my, name, is, Richard} 然后我在这里取出 {my} 和 {name} {Hello, my, name, is, Richard}。 结果:{你好,我的名字,是理查德}

    这种方法可以满足我的需要,但是对于解析大文件,这变得太重了,因为对于每个句子都需要太多的副本。所以我的问题是,我可以做些什么来将所有内容都包含在一个模式中?喜欢:

    "使用这种模式 "[\W+] 分割文本,但是如果你找到一个像 "aaa-aa" 这样的词,请认为它是一个词而不是两个词。

【问题讨论】:

    标签: java regex split


    【解决方案1】:

    如果您想使用 split() 而不是显式匹配您感兴趣的单词,以下应该做您想做的事情:[\s-]{2,}|\s 要打破它,您首先拆分两个或多个空格和/或连字符 - 所以单个 '-' 将不匹配,所以 'one-two' 将被单独留下,但类似 ​​'one--two'、'one - two' 甚至 'one - ---- - two' 将是分为“一”和“二”。这仍然使单个空格的“正常”情况 - “一二” - 不匹配,因此我们添加一个或('|'),后跟一个空格(\s)。请注意,备选方案的顺序很重要 - 由“|”分隔的 RE 子表达式从左到右进行评估,因此我们需要首先放置空格和连字符的替代方案。如果我们反其道而行之,当出现“one -two”之类的内容时,我们会匹配第一个空格并返回“one”、“-two”。

    如果您想以交互方式使用 Java RE,我完全可以推荐 http://myregexp.com/signedJar.html,它允许您编辑 RE 并在编辑 RE 时查看它与示例字符串的匹配情况。

    【讨论】:

    • 这很好用,但我想排除“word2car”作为一个词。相反,将考虑“单词”和“汽车”。有哪些必要的改变?
    • 这取决于 - 您希望所有出现的 '2' 都是单词分隔符,还是仅在特定单词之间?如果它在任何地方,您可以将 RE 更改为 \B2\B|[\s-]{2,}|\s。 \B 匹配非单词边界,因此它将拆分“ a2b ”,但不会拆分“ 2nd ”。但是,这也会将包含“2”的数字拆分为单独的部分,这可能不是您想要的。在这种情况下,(?<=\p{L})2(?=\p{L})|[\s-]{2,}|\s 可能就是您想要的 - '2' 两边都有一个字母、非数字字符。
    【解决方案2】:

    为什么不使用模式\\s+?这完全符合您的要求,没有任何技巧:按由空格分隔的单词分割文本。

    【讨论】:

    • 例如,我希望将“blue-sky”视为一个词,而不是两个词:{blue, sky}。
    • 好的,所以使用空格分割可以满足您的需求。试试看吧。
    • 实际上没有:p 我不想考虑这样的事情:“--- --- --”或“aaaa--”或“aaaa--aaaa-aaa”。
    【解决方案3】:

    你的描述不够清楚,为什么不用空格分开呢?

    【讨论】:

      【解决方案4】:

      我不确定这种模式是否可行,因为我没有 Java 开发工具,不过你可以尝试一下,它使用字符类减法,据我所知,它仅在 Java 正则表达式中受支持:

      [\W&&[^-]]+
      

      如果字符是[\W]和[^-]则表示匹配字符,即字符是[\W]而不是[-]。

      【讨论】:

        【解决方案5】:

        previous question 中的正则表达式几乎相同:

        String sentence = "Hello my-name is Richard";
        Pattern pattern = Pattern.compile("(?<!\\w)\\w+(-\\w+)?(?!\\w)");
        Matcher matcher = pattern.matcher(sentence);
        while (matcher.find()) {
            System.out.println(matcher.group());
        }
        

        刚刚添加了选项(...)? 也可以匹配非炒作词。

        【讨论】:

        • 工作出色。非常感谢,终于解决了这个噩梦。
        • 你能帮我一个忙,用 \\W 而不是 a-zA-a 更新代码。因为我也想允许 áíõ 等 ..
        • 我解决了添加这个:“À-ÿ”,但似乎如果我们输入一个单词而不是所有字母,该模式会运行得更快。你怎么看?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-07
        • 1970-01-01
        • 2012-08-25
        • 1970-01-01
        • 1970-01-01
        • 2015-12-29
        相关资源
        最近更新 更多