使用 IndexOf 获取带有空格和引号的字符串的子串

Get Substring of A String with Spaces and Quotes using IndexOf

我有以下字符串并想提取规则的内容,即我的规则描述如下所示:

rule "My Rule Description Looks Like This"      
        followed by some white space other characters such as quotes".

当我使用以下命令时,我得到一个 java.lang.StringIndexOutOfBoundsException:字符串索引超出范围:-2:

String ruleName = rule.substring(rule.indexOf("rule \"" + 7, rule.indexOf("\""));

当我使用 lastIndexOf:

String ruleName = rule.substring(rule.indexOf("rule \"" + 7, rule.lastIndexOf("\""));

代码执行正常,但输出如下:

My Rule Description Looks Like This"        
        followed by some white space other characters and quotes

知道为什么第一个选项使用 indexOf 抛出异常吗?

对于任何类型的复杂文本提取,您可能需要考虑使用正则表达式。这是一个可以提取规则的简短脚本,它避免了讨厌的字符串操作,如您所见,这种操作很容易出错。

String line = "rule \"My Rule Description Looks Like This\"\n";
line += "followed by some white space other characters such as quotes\".";
String pattern = "rule\s+\"(.*?)\".*";

Pattern r = Pattern.compile(pattern, Pattern.DOTALL);
Matcher m = r.matcher(line);
if (m.find()) {
   System.out.println("Found a rule: " + m.group(1) );
} else {
   System.out.println("Could not find a rule.");
}

输出:

My Rule Description Looks Like This

此处演示:

Rextester

来自 the documentation:

public String substring(int beginIndex, int endIndex)

if the beginIndex is negative, or endIndex is larger than the length of this String object, or beginIndex is larger than endIndex.

您正在呼叫 rule.substring(rule.indexOf("rule \"" + 7, rule.indexOf("\""))。第一个参数为您提供第一个 rule + quote 的索引,比方说 x,+ 7。第二个参数为您提供第一个引号的索引,即 x + 6 (x - rule 中的字符数。所以你正在调用 substring (x + 7, x +6),这属于异常情况:

first parameter biger than the second.

在你的第二种情况下,使用 lastIndexOf,你得到的是第二个引号,所以你没有这个问题。

indexOf returns 指定字符串 第一次出现 的索引。

因此,您的第一个示例将尝试从索引 7(0 是找到您的字符串的位置的索引,然后添加 7)开始子字符串,并以索引 5(找到第一个 " 的位置)结束。

substring(int beginIndex, int endIndex) 方法有一些逻辑,如果从结束索引中减去的开始索引小于 0 它会抛出一个 StringIndexOutOfBoundsException 值:

int subLen = endIndex - beginIndex;
if (subLen < 0) {
    throw new StringIndexOutOfBoundsException(subLen);
}

你的第二个例子没有抛出异常,但是因为你使用的是 lastIndexOf() 它将从 7 子字符串到字符串的末尾(那里有一个 ")。

最好的解决方案是使用@Tim Biegeleisen 的回答中所示的正则表达式模式