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

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

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

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

Text1 Text2 Text3 Text4

这就是我想要的

Text1 DelimiterA Text2 DelimiterC Text3 DelimiterB Text4

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


当前回答

我知道这是一个非常非常古老的问题,答案也被接受了。但我仍然想对最初的问题提出一个非常简单的答案。考虑下面的代码:

String str = "Hello-World:How\nAre You&doing";
inputs = str.split("(?!^)\\b");
for (int i=0; i<inputs.length; i++) {
   System.out.println("a[" + i + "] = \"" + inputs[i] + '"');
}

输出:

a[0] = "Hello"
a[1] = "-"
a[2] = "World"
a[3] = ":"
a[4] = "How"
a[5] = "
"
a[6] = "Are"
a[7] = " "
a[8] = "You"
a[9] = "&"
a[10] = "doing"

我只是使用单词边界\b来分隔单词,除非它是文本的开始。

其他回答

我不太懂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);

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

我不认为这是可能的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|'|

有点太多了……: -)

这个问题的一个微妙之处涉及到“前导分隔符”问题:如果要有一个组合的令牌和分隔符数组,则必须知道它是以令牌还是以分隔符开始的。你当然可以假设前导界限应该被丢弃,但这似乎是一个不合理的假设。你可能还想知道你是否有一个拖拽的delim。这将相应地设置两个布尔标志。

用Groovy编写,但Java版本应该相当明显:

            String tokenRegex = /[\p{L}\p{N}]+/ // a String in Groovy, Unicode alphanumeric
            def finder = phraseForTokenising =~ tokenRegex
            // NB in Groovy the variable 'finder' is then of class java.util.regex.Matcher
            def finderIt = finder.iterator() // extra method added to Matcher by Groovy magic
            int start = 0
            boolean leadingDelim, trailingDelim
            def combinedTokensAndDelims = [] // create an array in Groovy

            while( finderIt.hasNext() )
            {
                def token = finderIt.next()
                int finderStart = finder.start()
                String delim = phraseForTokenising[ start  .. finderStart - 1 ]
                // Groovy: above gets slice of String/array
                if( start == 0 ) leadingDelim = finderStart != 0
                if( start > 0 || leadingDelim ) combinedTokensAndDelims << delim
                combinedTokensAndDelims << token // add element to end of array
                start = finder.end()
            }
            // start == 0 indicates no tokens found
            if( start > 0 ) {
                // finish by seeing whether there is a trailing delim
                trailingDelim = start < phraseForTokenising.length()
                if( trailingDelim ) combinedTokensAndDelims << phraseForTokenising[ start .. -1 ]

                println( "leading delim? $leadingDelim, trailing delim? $trailingDelim, combined array:\n $combinedTokensAndDelims" )

            }

我建议使用Pattern和Matcher,这几乎肯定会达到你想要的效果。你的正则表达式需要比你在String.split中使用的更复杂一些。