【问题标题】:How to grab the string between the first and last occurrence of a hyphen如何在第一次和最后一次出现连字符之间获取字符串
【发布时间】:2019-09-23 16:31:57
【问题描述】:

我正在尝试制作一个程序,如果给定的字符串中有两个破折号,则返回前两个破折号之间的文本。如果它没有至少两个破折号,它将返回它不存在。前任。我有一个字符串

String s = "I AM -VERY- HUNGRY"

我希望我的程序返回 VERY,它位于两个破折号之间。到目前为止,这是我的代码

public static String middleText(String sentence)
   {
   int count = 0;
   for (int i = 0; i < sentence.length(); i++)
   {
     if (sentence.charAt(i) == '-')
     {
        count++;
     }
   } 
   if (count >= 2)
   {
     return sentence.substring(sentence.indexOf("-") + 1);
   }
   else
   {
     return "DOES NOT EXIST";
   }
}  

但是,此代码不会产生我想要的输出。如果我将字符串I AM -VERY- HUNGRY 放入此代码中,它将返回VERY- HUNGRY。我怎样才能让它只抓住文本直到第二个破折号?

【问题讨论】:

  • 跟踪字符在哪个索引处是 -。然后,在这些数字之间取一个子字符串...
  • sentence.indexOf("-") 返回第一个“-”的位置,substring 只有一个参数为您提供从该位置开始到结束的字符串。
  • 提示:当一切顺利时,您的方法应该返回一个 String。所以返回一个 String error 消息真的是个坏主意!使用该方法的代码必须检查返回的字符串是否不存在才能弄清楚发生了什么。风格不好!

标签: java regex string


【解决方案1】:

您可以使用以下行:

return sentence.substring(sentence.indexOf("-")+1, sentence.lastIndexOf("-"));

或者使用正则表达式。请参阅此案例的具体正则表达式链接Regex101

-(\w+)-

符合以下条件:

  • \w+ 表示任何字母至少出现一次+
  • () 正在捕获组
  • -(\w+)- 捕获 - 字符之间的一个或多个字母

结合PatternMatcher 来实现结果。

public static String middleText(String sentence) {
    Pattern pattern = Pattern.compile("-(\w)-");
    Matcher matcher = pattern.matcher(sentence);
    if (matcher.find()) {
        return matcher.group(1);
    } else {
        return "DOES NOT EXIST";
    }
}

【讨论】:

  • 您是想打电话给find()吗?否则它只会在字符串以破折号开头和结尾时才有效。
  • 是的,我的意思是find()。很抱歉,感谢您的编辑。
【解决方案2】:

您可以为此使用模式和匹配器 (java.util.regex)

String s = "I AM -VERY- HUNGRY";
Pattern patter = Pattern.compile("-(.*)-");
Matcher matcher = patter.matcher(s);
if (matcher.find()) {
    System.out.println(matcher.group(1)); // VERY
} else {
    System.out.println("no match");
}

【讨论】:

  • 如果你使用find(),你就不需要.*在开头和结尾。它也更直观,因为您确实在尝试找到破折号之间的文本。
【解决方案3】:

只需使用String的方法split即可。 See API here。使用字符串“-”作为分隔符,如果结果数组的长度为 3 或更长,那么 Array 的第二个成员就是您的结果:

public String myMatchFinder(String arg) {
    String result = null;
    String res[] = arg.split("-", 3);
    if(res.length == 3) {
      result = res[1];
    } else {
      throw new RuntimeException("No matches found");
    }
    return result;
}

如果没有找到模式,“else”块会起作用。因此,在这种情况下,异常被抛出作为不匹配的指示符,而不是返回一个可能与实际结果混淆的字符串。 (假设您的 arg 字符串是 "Hello -no matches found-bye"。在这种情况下,字符串 "no matches found" 将是您的实际结果)。因此,抛出异常后,您可以在调用代码中捕获它,并以任何您喜欢的方式将其作为错误处理。

【讨论】:

  • 这只是一个针对新手的简化示例。所以会很清楚。我当然不会把它写成真正的代码。我也(几乎)从来没有在同一个方法中多次返回,但这又是一个快速而肮脏的演示。所以从技术上讲你是正确的,但你只是在挑选细节,而原则解决方案是正确的并且是视觉演示
  • 好的,这样更好,我同意
  • 只剩下一件事 --- 该消息中有一个错字。你应该解释 else 块在做什么。
【解决方案4】:

您将希望使用indexOf 获取第一个连字符的索引,并使用lastIndexOf 获取最后一个连字符的索引。所以也许是这样的:

int firstIndex = sentence.indexOf("-");
int lastIndex = sentence.lastIndexOf("-");
return sentence.substring(firstIndex+1, lastIndex);

(注意:此代码未经测试,不包括您提到的那种错误检查。)

【讨论】:

    【解决方案5】:

    而单线解决方案...

    return Optional.of(sentence)
        .map(Pattern.compile("(?<=-).*?(?=-)")::matcher)
        .filter(Matcher::find)
        .map(Matcher::group)
        .orElse("DOES NOT EXIST");
    

    【讨论】:

      【解决方案6】:

      如果字符串格式一致 - 总是有两个连字符在其中包含一个值 - 您可以简单地使用 .replaceFirst^[^-]*-(.*)-[^-]*$ 正则表达式模式和替换中的 $1 占位符模式:

      String s = "I AM -VERY- HUNGRY"
      String result = s.replaceFirst("(?s)^[^-]*-(.*)-[^-]*$", "$1");
      

      请参阅 regex demoJava demo

      详情

      • (?s) - 一个 DOTALL 修饰符
      • ^ - 字符串开头
      • [^-]* - 除了- 之外还有 0+ 个字符
      • - - 一个连字符
      • (.*) - 第 1 组(与替换模式中的 $1 一起引用) - 尽可能多的任何 0+ 个字符
      • - - 一个连字符
      • [^-]* - 除了- 之外还有 0+ 个字符
      • $ - 字符串结束。

      如果可以有任何类型的连字符,请在代码中使用\\p{Pd} 而不是-

      【讨论】:

        猜你喜欢
        • 2017-08-20
        • 2022-10-13
        • 2013-12-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-11
        相关资源
        最近更新 更多