以下是直接解析的方法,其中提供的 #parse
方法可以根据您的需要集成到应用程序中:
private static List<String> parse(String input, String prefix, String suffix) {
int depth = 0; // 当前嵌套层级深度
int left = -1; // 标记变量,用于截取 depth==1 时的组
List<String> back = new ArrayList<>(); // 存储 depth==1 时观察到的组
for (int i = 0; i < input.length();) { // 遍历字符串逐字符查找组
if (input.startsWith(prefix, i)) {
// 发现一个组的起始分隔符,增加深度计数
depth++;
i += prefix.length(); // 跳过分隔符
if (depth == 1) {
// 记录从 depth 0 到 1 的位置以便后续截取子串
left = i;
}
} else if (depth > 0 && input.startsWith(suffix, i)) {
// 发现一个组的结束分隔符
// 检查 depth>0 以忽略未平衡括号外部的后缀
if (depth == 1) {
// 当 depth 从 1 变为 0 时截取结果
back.add(input.substring(left, i));
}
depth--;
i += suffix.length(); // 跳过分隔符
} else {
i++; // 继续迭代直到找到起始或结束分隔符
}
}
return back;
}
private static List<String> parseBrackets(String input) {
return parse(input, "[", "]");
}
public static void main(String[] args) {
// `tags` 内容:["Java [Script]", "Programming"]
List<String> tags = parseBrackets("This is a text [Java [Script]] [Programming]");
}
如您所见,使用方法非常简单,只需一行代码即可:
这个方法的整体性能为 O(n)
,并且在利用 String#indexOf
或正则表达式模式的解决方案中大致相当(可能优于后者)。这种方法无需维护状态,因此完全可以将其作为静态工具方法。总体而言,这是任何解析器后台都会进行的工作(某种形式的基于输入字符逐个操作的状态机)。