除括号内的空格外,将字符串按所有空格分割

10

可能重复:
基于正则表达式拆分字符串

我从未成为正则表达式大师,所以需要你们的帮助!我有一个像这样的字符串:

String s = "a [b c] d [e f g]";

我想使用空格作为分隔符来拆分这个字符串,但是我不想在[]括号中出现的空格上进行拆分。所以,从上面的例子中,我想得到以下数组:

{"a", "[b c]", "d", "[e f g]"}
任何建议可以与split一起使用的正则表达式以实现此目的?
这里有另一个例子:
"[a b] c [[d e] f g]"

变为

{"[a b]", "c", "[[d e] f g]"}

3
课程:正则表达式本课介绍正则表达式,它是一种用于在文本中搜索和匹配模式的工具。Java语言提供了对正则表达式的支持,并且其语法与其他语言中的正则表达式相似。您将学习如何使用Java中的Pattern和Matcher类来创建和匹配正则表达式。此外,我们还将讨论有关字符类、量词和分组等正则表达式的基本知识,并提供实际示例帮助您深入了解。本课程旨在帮助您掌握 Java 中的正则表达式,以便您可以更有效地处理文本数据。 - user1329572
@artbristol 是的,他们可以。我希望在任何括号集合内部不发生分割。我编辑了另一个例子。 - arshajii
2
@A.R.S,如果你不能使用正则表达式完成它,那么就需要编写解析器了。 - Carl Norum
2
这是第三个完全重复的问题.. 这个这个 - Anirudha
@CarlNorum 你可以……查看我回答的上面类似的问题。 - Anirudha
5个回答

10

我认为这应该能够工作,使用负向先行断言 - 它匹配在没有开括号的情况下出现在闭括号之前的任何空格:

"a [b c] d [e f g]".split("\\s+(?![^\\[]*\\])");

对于嵌套括号,你需要编写一个解析器,正则表达式无法处理无限级别并且在处理一两个级别以上时会变得过于复杂。例如,我的表达式无法处理以下情况:

"[a b [c d] e] f g"

2
它无法编译 - 我得到了“格式错误的正则表达式”错误。 - Nir Alfasi
@Jimmy:我刚刚编辑了转义字符,在此之前是“…[^[]…” - Bergi
@Bergi 是的- 更正后的版本可以工作!+1 - Nir Alfasi
@Bergi,如何在Express中以空格分割,但忽略()中的空格而不是{}呢? - Code Drop
@DanielNascimento 只需将正则表达式中的 \[\] 分别替换为 \(\) 即可。 - Bergi
显示剩余3条评论

3

正如其他答案所说,您需要一个解析器。 这是一个之前的正则表达式解决方案无法处理的字符串。

"[a b] c [a [d e] f g]"

编辑:

public static List<String> split(String s){
    List<String> l = new LinkedList<String>();
    int depth=0;
    StringBuilder sb = new StringBuilder();
    for(int i=0; i<s.length(); i++){
        char c = s.charAt(i);
        if(c=='['){
            depth++;
        }else if(c==']'){
            depth--;
        }else if(c==' ' && depth==0){
            l.add(sb.toString());
            sb = new StringBuilder();
            continue;
        }
        sb.append(c);
    }
    l.add(sb.toString());

    return l;
}

你可以使用正则表达式来完成它,不需要解析器。 - Anirudha
3
你如何使用正则表达式处理多重嵌套的 []? - Marco Martinelli

3
你不能用单个正则表达式实现这个,因为它无法匹配开/闭括号和处理嵌套的括号。
正则表达式不是图灵完备的,所以即使看起来可能有效,仍然会有失败的情况。
因此,我建议编写自己的几行代码来处理所有情况。
你可以为JavaCCAntLR创建非常简单的语法,或者使用简单的基于堆栈的解析器。

[[xx], [y]] z t [z [x] y]请继续。 - jdevelop
在C#中可以工作,但在Java中却不行...这要归功于Java对回顾后发支持有限。 - Anirudha
正则表达式中的回溯/向前查看和其他受 Perl 启发的内容与正则表达式本身无关。这个问题涉及到 Java,我不太关心 C# 或 Perl 中能用什么。 - jdevelop
对我来说这是一个bug...C#会这么做,为什么Java不行呢? - Anirudha
为什么我或TS关心C#?它是Java。C#缺乏JDBC/JMS支持,这是C#的一个缺陷。 - jdevelop
显示剩余5条评论

0

如果我正确理解了你的问题,那么答案可能是遵循规则4。

rule1 -> ((a-z).(\w))*.(a-z)

rule2 -> ([).rule1.(])

rule3 -> ([).(rule1.(\w))*.rule2.((\w).rule1)*.(])

rule4 -> rule1 | rule3

-1

对于非嵌套情况

\\s+(?![^\\[]*\\])

嵌套的([] 内部 [])

(?<!\\[[^\\]]*)\\s+(?![^\\[]*\\])

第一个正则表达式也是同样的事情。 - arshajii
@A.R.S. 尝试移除转义字符 \。 - Anirudha
@Anirudha 我成功地让第一个正则表达式工作了,但是第二个还有些问题。 - arshajii
@Anirudha:Java的后顾之忧非常有限。 - Bergi
@Bergi这是否意味着Java中不存在此正则表达式的等效物? - arshajii
显示剩余5条评论

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