我有一个多行字符串,由一组不同的分隔符分隔:

(Text1)(DelimiterA)(Text2)(DelimiterC)(Text3)(DelimiterB)(Text4)

我可以使用string将这个字符串分割成各个部分。分裂,但似乎我无法获得与分隔符正则表达式匹配的实际字符串。

换句话说,这就是我得到的结果:

Text1 Text2 Text3 Text4

这就是我想要的

Text1 DelimiterA Text2 DelimiterC Text3 DelimiterB Text4

JDK中是否有任何方法可以使用分隔符正则表达式分割字符串,但同时保留分隔符?


当前回答

如果你想保留字符,那么使用split方法,该方法存在.split()方法中的漏洞。

请看这个例子:

public class SplitExample {


    public static void main(String[] args) {  
        String str = "Javathomettt";  
        System.out.println("method 1");
        System.out.println("Returning words:");  
        String[] arr = str.split("t", 40);  
        for (String w : arr) {  
            System.out.println(w+"t");  
        }  
        System.out.println("Split array length: "+arr.length);  
        System.out.println("method 2");
        System.out.println(str.replaceAll("t", "\n"+"t"));
    }

其他回答

另一个使用正则表达式的候选解决方案。保留令牌顺序,正确匹配一行中相同类型的多个令牌。缺点是正则表达式有点讨厌。

package javaapplication2;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JavaApplication2 {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        String num = "58.5+variable-+98*78/96+a/78.7-3443*12-3";

        // Terrifying regex:
        //  (a)|(b)|(c) match a or b or c
        // where
        //   (a) is one or more digits optionally followed by a decimal point
        //       followed by one or more digits: (\d+(\.\d+)?)
        //   (b) is one of the set + * / - occurring once: ([+*/-])
        //   (c) is a sequence of one or more lowercase latin letter: ([a-z]+)
        Pattern tokenPattern = Pattern.compile("(\\d+(\\.\\d+)?)|([+*/-])|([a-z]+)");
        Matcher tokenMatcher = tokenPattern.matcher(num);

        List<String> tokens = new ArrayList<>();

        while (!tokenMatcher.hitEnd()) {
            if (tokenMatcher.find()) {
                tokens.add(tokenMatcher.group());
            } else {
                // report error
                break;
            }
        }

        System.out.println(tokens);
    }
}

样例输出:

[58.5, +, variable, -, +, 98, *, 78, /, 96, +, a, /, 78.7, -, 3443, *, 12, -, 3]

我不太懂Java,但如果你找不到一个Split方法,我建议你自己做一个。

string[] mySplit(string s,string delimiter)
{
    string[] result = s.Split(delimiter);
    for(int i=0;i<result.Length-1;i++)
    {
        result[i] += delimiter; //this one would add the delimiter to each items end except the last item, 
                    //you can modify it however you want
    }
}
string[] res = mySplit(myString,myDelimiter);

它不是很优雅,但也可以。

我来晚了,但回到最初的问题,为什么不使用搜索呢?

Pattern p = Pattern.compile("(?<=\\w)(?=\\W)|(?<=\\W)(?=\\w)");
System.out.println(Arrays.toString(p.split("'ab','cd','eg'")));
System.out.println(Arrays.toString(p.split("boo:and:foo")));

输出:

[', ab, ',', cd, ',', eg, ']
[boo, :, and, :, foo]

编辑:您在上面看到的是我运行该代码时命令行上出现的内容,但我现在看到它有点令人困惑。很难跟踪哪些逗号是结果的一部分,哪些是由Arrays.toString()添加的。SO的语法高亮显示也没有帮助。为了让突出显示与我一起工作而不是反对我,下面是我在源代码中声明这些数组的样子:

{ "'", "ab", "','", "cd", "','", "eg", "'" }
{ "boo", ":", "and", ":", "foo" }

我希望这更容易理解。谢谢你的提醒,@finnw。

我不认为这是可能的String#split,但你可以使用一个StringTokenizer,虽然它不允许你定义你的分隔符作为一个正则表达式,但只能作为一个类的个位数字符:

new StringTokenizer("Hello, world. Hi!", ",.!", true); // true for returnDelims

快速回答:使用非物理边界,如\b分割。我将尝试和实验,看看它是否有效(在PHP和JS中使用)。

这是可能的,也是一种工作,但可能会分裂太多。实际上,这取决于你想拆分的字符串和你需要的结果。提供更多细节,我们将更好地帮助您。

另一种方法是自己进行拆分,捕获分隔符(假设它是可变的),然后将其添加到结果中。

我的快速测试:

String str = "'ab','cd','eg'";
String[] stra = str.split("\\b");
for (String s : stra) System.out.print(s + "|");
System.out.println();

结果:

'|ab|','|cd|','|eg|'|

有点太多了……: -)