如何抓取破折号首尾之间的字符串

4

我正在尝试编写一个程序,如果给定了一个带有两个破折号的字符串,它会返回第一个和第二个破折号之间的文本。如果没有至少两个破折号,它将返回不存在。例如,我有一个字符串:

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 "。我该如何使它仅获取文本直到第二个破折号?

记录字符的索引位置。然后,在这些数字之间取一个子字符串... - Andrew Li
sentence.indexOf("-") 返回第一个 "-" 的位置,而只有一个参数的 substring 方法则返回从该位置到字符串末尾的子串。 - Sentry
提示: 当一切正常时,您的方法应返回一个 **字符串(String)**。因此,返回一个 错误 信息字符串确实是一个不好的主意!使用该方法的代码将不得不检查返回的字符串是否为“不存在”,以确定发生了什么。这是一种糟糕的风格! - GhostCat
6个回答

7
你可以使用以下代码行:
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";
    }
}

1
你是不是想调用 find() 函数?否则,它只会在字符串以破折号开头和结尾时才起作用。 - Andreas
是的,我指的是 find()。对不起并感谢您的编辑。 - Nikolas Charalambidis

2
您可以使用Pattern和Matcher(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(),则不需要在开头和结尾使用 .*。这也更加直观,因为您确实是在尝试查找破折号之间的文本。 - Andreas

2

只需使用String的split方法即可。查看API。使用“-”作为分隔符,如果您的结果数组长度为3或更多,则第二个成员即为您的结果:

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"块用于在没有找到模式时工作。因此,在这种情况下,异常被抛出作为未匹配的指示器,而不是返回一个可能被误认为是实际结果的字符串(假设您的参数字符串是"Hello -no matches found- bye"。在这种情况下,字符串"no matches found"将是您的实际结果)。因此,通过抛出异常,您可以在调用代码中捕获它并按任何您喜欢的方式处理它。


这只是一个新手的简化示例,以便清晰易懂。我肯定不会将其编写为真正的代码。我也几乎从不在同一方法中使用多个返回,但这只是一个快速而粗略的演示。所以从技术上讲,你是正确的,但你只是在挑剔细节,而原则性的解决方案是正确的,并且已经通过视觉展示了出来。 - Michael Gantman
好的,这样更好,我同意。 - Michael Gantman
只剩下一件事——那条信息中有一个错别字。而且你应该解释那个else块是在做什么。 - GhostCat

1
如果字符串格式是一致的 - 总是有两个带有值的连字符 - 您可以简单地使用 .replaceFirst^[^-]*-(.*)-[^-]*$ 正则表达式模式以及替换模式中的 $1 占位符。
String s = "I AM -VERY- HUNGRY"
String result = s.replaceFirst("(?s)^[^-]*-(.*)-[^-]*$", "$1");

查看正则表达式演示Java演示

详细信息

  • (?s) - DOTALL 修饰符
  • ^ - 字符串的开头
  • [^-]* - 除了 - 之外的任意字符 0 次或多次
  • - - 连字符
  • (.*) - 第一组(在替换模式中称为 $1)- 匹配任意字符 0 次或多次,尽可能多地匹配
  • - - 连字符
  • [^-]* - 除了 - 之外的任意字符 0 次或多次
  • $ - 字符串的结尾。

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


1
"一行解决方案..."
return Optional.of(sentence)
    .map(Pattern.compile("(?<=-).*?(?=-)")::matcher)
    .filter(Matcher::find)
    .map(Matcher::group)
    .orElse("DOES NOT EXIST");

1
你需要使用indexOf来获取第一个连字符的索引,使用lastIndexOf来获取最后一个连字符的索引。因此,可能会像这样:
int firstIndex = sentence.indexOf("-");
int lastIndex = sentence.lastIndexOf("-");
return sentence.substring(firstIndex+1, lastIndex);

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接