【问题标题】:Java - Search for words having more than 1 capital letterJava - 搜索超过 1 个大写字母的单词
【发布时间】:2010-07-22 16:03:08
【问题描述】:

在 Java 中搜索任务时需要您的帮助。 我需要从文件中读取一行并列出所有包含超过 1 个大写字母的单词。

例如,如果行是:There are SeVen Planets In this UniverSe

结果应该是:SeVen 和 UniverSe

我可以通过将其拆分为单词来阅读该行,但有些无法使用正确的正则表达式来搜索这些单词。

以下是我使用的一个小例子,虽然我认为它应该返回 true,但它返回 false。

System.out.println("ThiS".matches("[A-Z]{2,}"));

任何人都可以看看这个并提出实现我的结果的方法吗? 感谢任何帮助。

谢谢,

AJ

【问题讨论】:

  • 在您担心将其转换为正则表达式语法的细节之前,请尝试用文字描述与您想要的规则相匹配的规则。例如,“大写单词”的描述可能是“一个大写字母,后跟任意数量的小写字母”,您可以将其翻译为“^[A-Z][a-z]*$”

标签: java regex search


【解决方案1】:

[A-Z]{2,} 表示 2 个或多个连续的大写字母。您可以使用[A-Z].*[A-Z],这将允许任何其他字符出现在两个大写字母之间。

或者,您实际上并不需要为此使用正则表达式。如果您愿意,您可以遍历字符串中的每个字符并使用 Character.isUpperCase 并计算匹配字符的数量。

【讨论】:

  • 我喜欢字符串迭代。简单易懂。
  • 匹配SeVen Planets In this UniverS,懒惰匹配SeV。您需要使用\b[A-Z].*?[A-Z].*?\b 定义单词边界,这是非常低效的。也许原子分组或向前看会更好。
  • @fy-tide 从问题的措辞来看,我假设 OP 已经将字符串拆分为单个单词,因此我们只需要一种获取 true/false 的方法来指示单个单词是否具有 > = 2 个大写字母。
  • @fy-tide:单词边界解决方案也不起作用,因为它可以匹配The Earth,因为在“The”之前和“Earth”之后有一个单词边界,并且. 匹配空格。
  • @Mark Peters True,\w 边界对于整个字符串来说会更好,就像其他答案一样。
【解决方案2】:

也许[a-z]*[A-Z][a-z]*[A-Z][a-z]* 可以工作。事实是用{..} 计数不允许两个字母之间的字符。

【讨论】:

    【解决方案3】:
    \b(?:[a-z]*[A-Z]){2}[a-z]*\b
    

    将匹配至少包含两个大写字母的单词。

    如果您想允许包含非 ASCII 字母的单词,请使用

    \b(?:\p{Ll}*\p{Lu}){2}\p{Ll}*\b
    

    当然,在 Java 字符串中,您需要转义(双)反斜杠。

    所以你得到:

    Pattern regex = Pattern.compile("\\b(?:\\p{Ll}*\\p{Lu}){2}\\p{Ll}*\\b");
    Matcher regexMatcher = regex.matcher(subjectString);
    while (regexMatcher.find()) {
        // matched text: regexMatcher.group()
        // match start: regexMatcher.start()
        // match end: regexMatcher.end()
    }
    

    【讨论】:

      【解决方案4】:

      您列出的正则表达式不起作用,因为它会搜索 2 个或更多大写字母的连续序列。

      我认为您需要做的是编写一个表达式,让您在两边都允许小写字母。

      我不记得确切的语法(我要检查一下),但像 .*[A-Z].*[A-Z].* 这样的东西会确保你有两个大写字母

      【讨论】:

        【解决方案5】:

        您当前的正则表达式仅匹配两个或多个大写字母的序列,而不是遍布整个单词的多个字母。因此,您将匹配 THistHIS 而不是您发现的 ThiS

        您需要查找一个大写字母,可能是一些小写字母,然后是另一个大写字母。或者在正则表达式中:[A-Z]\w*?[A-Z]

        如果你想搜索整个字符串而不需要先拆分它,那么在任一端包含其他单词字符的可能性并让表达式捕获:(\w*?[A-Z]\w*?[A-Z]\w*)

        还请注意,我们使用了不情愿的量词,以便它们在前两个实例中尽早停止匹配,并在末尾使用正常(贪婪)量词来获取单词的其余部分。阅读有关各种量词的更多信息here

        【讨论】:

          【解决方案6】:
              Pattern pat = Pattern.compile("\\w*[A-Z]\\w*[A-Z]\\w*");
              Matcher matcher = pat.matcher("There are SeVen Planets In this UniverSe");
              while ( matcher.find() ) {
                  System.out.println(matcher.group());
              }
          

          打印

          SeVen
          UniverSe
          

          虽然我对正则表达式很糟糕,所以可能有一种更简单的方法。不过这种方式很容易理解:从单词的开头开始,匹配 0 个或多个字符,然后是一个大写字符,然后是 0 个或多个字符,然后是另一个大写字符,然后是 0 个或多个字符。

          【讨论】:

          • 您不需要单词边界,因为单词字符无论如何都不会匹配前面的非单词字符。
          • @MikeD,好点;当我把它放进去时,我最初并没有使用类这个词。
          • 嘿,马克...必须说你对正则表达式很擅长!您提供的示例代码似乎有效:) 非常感谢您的输入。 MikeJ、Jack、Uri、Tim 和 MikeD...谢谢大家的快速回复顺便说一句,正则表达式让我忘记了实际上有多少行星:p 感谢您的所有时间..再次感谢! -AJS
          【解决方案7】:

          我使用这个正则表达式/[A-Z].[A-Z]+/

          【讨论】:

          • /[A-Z].*[A-Z]+/ 不是更好吗?我认为您提出的正则表达式将匹配 AbC 但不匹配 AbcD
          【解决方案8】:

          你可以使用这个正则表达式:

          "SeVen".matches("[A-Z].[A-Z][a-zA-Z]") //true

          "SeveNEight".matches("[A-Z].[A-Z][a-zA-Z]") //true

          "seVeneight".matches("[A-Z].[A-Z][a-zA-Z]") //假

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-12-26
            • 1970-01-01
            • 1970-01-01
            • 2020-08-30
            • 1970-01-01
            • 1970-01-01
            • 2021-11-30
            相关资源
            最近更新 更多