如何分割一个字符串,但也保持分隔符?

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

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

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

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

  • Text1
  • Text2
  • Text3
  • Text4

这就是我想要的

  • Text1
  • DelimiterA
  • Text2
  • DelimiterC
  • Text3
  • DelimiterB
  • Text4

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

179177 次浏览

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

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

快速回答:使用非物理边界,如\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|'|

有点太多了……: -)

我不知道Java API中是否存在这样做的现有函数(这并不是说它不存在),但这是我自己的实现(一个或多个分隔符将作为单个令牌返回;如果你想让每个分隔符作为一个单独的标记返回,它将需要一些适应):

static String[] splitWithDelimiters(String s) {
if (s == null || s.length() == 0) {
return new String[0];
}
LinkedList<String> result = new LinkedList<String>();
StringBuilder sb = null;
boolean wasLetterOrDigit = !Character.isLetterOrDigit(s.charAt(0));
for (char c : s.toCharArray()) {
if (Character.isLetterOrDigit(c) ^ wasLetterOrDigit) {
if (sb != null) {
result.add(sb.toString());
}
sb = new StringBuilder();
wasLetterOrDigit = !wasLetterOrDigit;
}
sb.append(c);
}
result.add(sb.toString());
return result.toArray(new String[0]);
}
我喜欢StringTokenizer的想法,因为它是可枚举的 但它也是过时的,可以用String代替。

. split返回一个单调的字符串[](并且不包括分隔符)

所以我实现了一个StringTokenizerEx,它是一个Iterable,它接受一个真正的regexp来分割字符串。

一个真正的regexp意味着它不是一个重复的'字符序列'来形成分隔符:
'o'只匹配'o',并将'ooo'分成三个分隔符,其中有两个空字符串:

[o], '', [o], '', [o]

但是regexp o+在拆分“aooob”时将返回预期的结果

[], 'a', [ooo], 'b', []

使用StringTokenizerEx:

final StringTokenizerEx aStringTokenizerEx = new StringTokenizerEx("boo:and:foo", "o+");
final String firstDelimiter = aStringTokenizerEx.getDelimiter();
for(String aString: aStringTokenizerEx )
{
// uses the split String detected and memorized in 'aString'
final nextDelimiter = aStringTokenizerEx.getDelimiter();
}

该类的代码可在DZone Snippets中找到。

通常对于< >强code-challenge < / >强响应(一个包含测试用例的自包含类),复制粘贴,(在'src/test'目录中)和运行它。它的main()方法说明了不同的用法。


注:(2009年底编辑)

文章最后的想法:Java puzzle: Splitting hair很好地解释了String.split()中的奇怪行为 乔希·布洛赫甚至在回应那篇文章时评论道:

是的,这很痛苦。FWIW,这样做有一个很好的理由:与Perl兼容 做这件事的人是Mike "madbot" McCloskey,他现在在谷歌和我们一起工作。Mike确保Java的正则表达式通过了几乎每一个30K Perl正则表达式测试(并且运行得更快)

谷歌< >强公共图书馆番石榴< / >强还包含一个Splitter,它是:

  • 使用更简单
  • 由谷歌(而不是你)维护

所以它可能值得一看。从他们的初步文件(pdf):

JDK有:

String[] pieces = "foo.bar".split("\\.");

如果你想要它所做的,使用它是很好的: -正则表达式 - result作为数组 -它处理空块的方式

小谜题:",a,,b,".split(",")返回…

(a) "", "a", "", "b", ""
(b) null, "a", null, "b", null
(c) "a", null, "b"
(d) "a", "b"
(e) None of the above

答案:(e)以上都不是。

",a,,b,".split(",")
returns
"", "a", "", "b"

只跳过尾随空!(谁知道防止跳过的变通方法?这是一个有趣的…)

在任何情况下,我们的Splitter都更加灵活:默认行为很简单:

Splitter.on(',').split(" foo, ,bar, quux,")
--> [" foo", " ", "bar", " quux", ""]

如果您想要额外的功能,请提出要求!

Splitter.on(',')
.trimResults()
.omitEmptyStrings()
.split(" foo, ,bar, quux,")
--> ["foo", "bar", "quux"]

配置方法的顺序并不重要——在分割过程中,在检查空之前进行修整。

import java.util.regex.*;
import java.util.LinkedList;


public class Splitter {
private static final Pattern DEFAULT_PATTERN = Pattern.compile("\\s+");


private Pattern pattern;
private boolean keep_delimiters;


public Splitter(Pattern pattern, boolean keep_delimiters) {
this.pattern = pattern;
this.keep_delimiters = keep_delimiters;
}
public Splitter(String pattern, boolean keep_delimiters) {
this(Pattern.compile(pattern==null?"":pattern), keep_delimiters);
}
public Splitter(Pattern pattern) { this(pattern, true); }
public Splitter(String pattern) { this(pattern, true); }
public Splitter(boolean keep_delimiters) { this(DEFAULT_PATTERN, keep_delimiters); }
public Splitter() { this(DEFAULT_PATTERN); }


public String[] split(String text) {
if (text == null) {
text = "";
}


int last_match = 0;
LinkedList<String> splitted = new LinkedList<String>();


Matcher m = this.pattern.matcher(text);


while (m.find()) {


splitted.add(text.substring(last_match,m.start()));


if (this.keep_delimiters) {
splitted.add(m.group());
}


last_match = m.end();
}


splitted.add(text.substring(last_match));


return splitted.toArray(new String[splitted.size()]);
}


public static void main(String[] argv) {
if (argv.length != 2) {
System.err.println("Syntax: java Splitter <pattern> <text>");
return;
}


Pattern pattern = null;
try {
pattern = Pattern.compile(argv[0]);
}
catch (PatternSyntaxException e) {
System.err.println(e);
return;
}


Splitter splitter = new Splitter(pattern);


String text = argv[1];
int counter = 1;
for (String part : splitter.split(text)) {
System.out.printf("Part %d: \"%s\"\n", counter++, part);
}
}
}


/*
Example:
> java Splitter "\W+" "Hello World!"
Part 1: "Hello"
Part 2: " "
Part 3: "World"
Part 4: "!"
Part 5: ""
*/

我不太喜欢另一种方式,前后都有一个空元素。分隔符通常不在字符串的开头或结尾,因此通常会浪费两个良好的数组插槽。

编辑:固定限制情况。带有测试用例的注释源代码可以在这里找到:http://snippets.dzone.com/posts/show/6453

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

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的语法高亮显示也没有帮助。为了让突出显示工作 me而不是反对我,下面是我在源代码中声明这些数组的样子:

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

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

我看了一下上面的答案,老实说,没有一个让我满意。您要做的实际上是模拟Perl分割功能。为什么Java不允许这样做,并且在某个地方有一个join()方法,这超出了我的范围,但我离题了。你甚至不需要专门的课程。它只是一个函数。运行这个示例程序:

一些早期的答案有过多的空检查,我最近写了一个回答这里的问题:

https://stackoverflow.com/users/18393/cletus < a href = " https://stackoverflow.com/users/18393/cletus " > < / >

不管怎样,代码:

public class Split {
public static List<String> split(String s, String pattern) {
assert s != null;
assert pattern != null;
return split(s, Pattern.compile(pattern));
}


public static List<String> split(String s, Pattern pattern) {
assert s != null;
assert pattern != null;
Matcher m = pattern.matcher(s);
List<String> ret = new ArrayList<String>();
int start = 0;
while (m.find()) {
ret.add(s.substring(start, m.start()));
ret.add(m.group());
start = m.end();
}
ret.add(start >= s.length() ? "" : s.substring(start));
return ret;
}


private static void testSplit(String s, String pattern) {
System.out.printf("Splitting '%s' with pattern '%s'%n", s, pattern);
List<String> tokens = split(s, pattern);
System.out.printf("Found %d matches%n", tokens.size());
int i = 0;
for (String token : tokens) {
System.out.printf("  %d/%d: '%s'%n", ++i, tokens.size(), token);
}
System.out.println();
}


public static void main(String args[]) {
testSplit("abcdefghij", "z"); // "abcdefghij"
testSplit("abcdefghij", "f"); // "abcde", "f", "ghi"
testSplit("abcdefghij", "j"); // "abcdefghi", "j", ""
testSplit("abcdefghij", "a"); // "", "a", "bcdefghij"
testSplit("abcdefghij", "[bdfh]"); // "a", "b", "c", "d", "e", "f", "g", "h", "ij"
}
}

我认为使用String#split是不可能的,但你可以使用StringTokenizer,尽管它不允许你将分隔符定义为正则表达式,而只能定义为一组个位数字符:

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

您可以使用前向和后向,这是正则表达式的特性。

System.out.println(Arrays.toString("a;b;c;d".split("(?<=;)")));
System.out.println(Arrays.toString("a;b;c;d".split("(?=;)")));
System.out.println(Arrays.toString("a;b;c;d".split("((?<=;)|(?=;))")));

你会得到:

[a;, b;, c;, d]
[a, ;b, ;c, ;d]
[a, ;, b, ;, c, ;, d]

最后一个是你想要的。

((?<=;)|(?=;))等于在;之前或;之后选择一个空字符。

Fabian Steeg关于可读性的评论是有效的。可读性一直是正则表达式的一个问题。为了使正则表达式更具可读性,我做的一件事是创建一个变量,其名称表示正则表达式的功能。你甚至可以放置占位符(例如%1$s),并使用Java的String.format将占位符替换为你需要使用的实际字符串;例如:

static public final String WITH_DELIMITER = "((?<=%1$s)|(?=%1$s))";


public void someMethod() {
final String[] aEach = "a;b;c;d".split(String.format(WITH_DELIMITER, ";"));
...
}

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

一个不涉及regex的非常简单的解决方案是在分隔符上执行字符串替换(假设分隔符为逗号):

string.replace(FullString, "," , "~,~")

在这里,您可以用适当的惟一分隔符替换tilda(~)。

然后,如果您对新的分隔符进行拆分,那么我相信您将得到所需的结果。

如果你负担得起,使用Java的replace(CharSequence target, CharSequence replacement)方法,并填充另一个分隔符。 例子: 我想拆分字符串"boo:and:foo",并保持':'在它的右手string .

String str = "boo:and:foo";
str = str.replace(":","newdelimiter:");
String[] tokens = str.split("newdelimiter");
重要提示:这只在你的字符串中没有进一步的“newdelimiter”时才有效!因此,这不是一个通解。 但如果你知道一个CharSequence,你可以确定它永远不会出现在String中,这是一个非常简单的解决方案

您希望使用查找,并在零宽度匹配时进行分割。下面是一些例子:

public class SplitNDump {
static void dump(String[] arr) {
for (String s : arr) {
System.out.format("[%s]", s);
}
System.out.println();
}
public static void main(String[] args) {
dump("1,234,567,890".split(","));
// "[1][234][567][890]"
dump("1,234,567,890".split("(?=,)"));
// "[1][,234][,567][,890]"
dump("1,234,567,890".split("(?<=,)"));
// "[1,][234,][567,][890]"
dump("1,234,567,890".split("(?<=,)|(?=,)"));
// "[1][,][234][,][567][,][890]"


dump(":a:bb::c:".split("(?=:)|(?<=:)"));
// "[][:][a][:][bb][:][:][c][:]"
dump(":a:bb::c:".split("(?=(?!^):)|(?<=:)"));
// "[:][a][:][bb][:][:][c][:]"
dump(":::a::::b  b::c:".split("(?=(?!^):)(?<!:)|(?!:)(?<=:)"));
// "[:::][a][::::][b  b][::][c][:]"
dump("a,bb:::c  d..e".split("(?!^)\\b"));
// "[a][,][bb][:::][c][  ][d][..][e]"


dump("ArrayIndexOutOfBoundsException".split("(?<=[a-z])(?=[A-Z])"));
// "[Array][Index][Out][Of][Bounds][Exception]"
dump("1234567890".split("(?<=\\G.{4})"));
// "[1234][5678][90]"


// Split at the end of each run of letter
dump("Boooyaaaah! Yippieeee!!".split("(?<=(?=(.)\\1(?!\\1))..)"));
// "[Booo][yaaaa][h! Yipp][ieeee][!!]"
}
}

是的,在最后一个模式中是三重嵌套断言。

相关问题

另请参阅

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

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来分隔单词除了,当它是文本的开始。

调整Pattern.split ()以将匹配的模式包含到列表中

添加

// add match to the list
matchList.add(input.subSequence(start, end).toString());

完整的源

public static String[] inclusiveSplit(String input, String re, int limit) {
int index = 0;
boolean matchLimited = limit > 0;
ArrayList<String> matchList = new ArrayList<String>();


Pattern pattern = Pattern.compile(re);
Matcher m = pattern.matcher(input);


// Add segments before each match found
while (m.find()) {
int end = m.end();
if (!matchLimited || matchList.size() < limit - 1) {
int start = m.start();
String match = input.subSequence(index, start).toString();
matchList.add(match);
// add match to the list
matchList.add(input.subSequence(start, end).toString());
index = end;
} else if (matchList.size() == limit - 1) { // last one
String match = input.subSequence(index, input.length())
.toString();
matchList.add(match);
index = end;
}
}


// If no match was found, return this
if (index == 0)
return new String[] { input.toString() };


// Add remaining segment
if (!matchLimited || matchList.size() < limit)
matchList.add(input.subSequence(index, input.length()).toString());


// Construct result
int resultSize = matchList.size();
if (limit == 0)
while (resultSize > 0 && matchList.get(resultSize - 1).equals(""))
resultSize--;
String[] result = new String[resultSize];
return matchList.subList(0, resultSize).toArray(result);
}

这是一个极其幼稚和低效的解决方案,但它仍然有效。对字符串使用两次split,然后连接两个数组

String temp[]=str.split("\\W");
String temp2[]=str.split("\\w||\\s");
int i=0;
for(String string:temp)
System.out.println(string);
String temp3[]=new String[temp.length-1];
for(String string:temp2)
{
System.out.println(string);
if((string.equals("")!=true)&&(string.equals("\\s")!=true))
{
temp3[i]=string;
i++;
}
//      System.out.println(temp.length);
//      System.out.println(temp2.length);
}
System.out.println(temp3.length);
String[] temp4=new String[temp.length+temp3.length];
int j=0;
for(i=0;i<temp.length;i++)
{
temp4[j]=temp[i];
j=j+2;
}
j=1;
for(i=0;i<temp3.length;i++)
{
temp4[j]=temp3[i];
j+=2;
}
for(String s:temp4)
System.out.println(s);

下面是一个基于上面一些代码的groovy版本,以防有用。不管怎样,它很短。有条件地包括头部和尾部(如果它们不是空的)。最后一部分是演示/测试用例。

List splitWithTokens(str, pat) {
def tokens=[]
def lastMatch=0
def m = str=~pat
while (m.find()) {
if (m.start() > 0) tokens << str[lastMatch..<m.start()]
tokens << m.group()
lastMatch=m.end()
}
if (lastMatch < str.length()) tokens << str[lastMatch..<str.length()]
tokens
}


[['<html><head><title>this is the title</title></head>',/<[^>]+>/],
['before<html><head><title>this is the title</title></head>after',/<[^>]+>/]
].each {
println splitWithTokens(*it)
}

传递第三个参数为“true”。它还将返回分隔符。

StringTokenizer(String str, String delimiters, true);

我也会发布我的工作版本(第一个是真的类似Markus)。

public static String[] splitIncludeDelimeter(String regex, String text){
List<String> list = new LinkedList<>();
Matcher matcher = Pattern.compile(regex).matcher(text);


int now, old = 0;
while(matcher.find()){
now = matcher.end();
list.add(text.substring(old, now));
old = now;
}


if(list.size() == 0)
return new String[]{text};


//adding rest of a text as last element
String finalElement = text.substring(old);
list.add(finalElement);


return list.toArray(new String[list.size()]);
}

这是第二个解,比第一个快50%

public static String[] splitIncludeDelimeter2(String regex, String text){
List<String> list = new LinkedList<>();
Matcher matcher = Pattern.compile(regex).matcher(text);


StringBuffer stringBuffer = new StringBuffer();
while(matcher.find()){
matcher.appendReplacement(stringBuffer, matcher.group());
list.add(stringBuffer.toString());
stringBuffer.setLength(0); //clear buffer
}


matcher.appendTail(stringBuffer); ///dodajemy reszte  ciagu
list.add(stringBuffer.toString());


return list.toArray(new String[list.size()]);
}
    String expression = "((A+B)*C-D)*E";
expression = expression.replaceAll("\\+", "~+~");
expression = expression.replaceAll("\\*", "~*~");
expression = expression.replaceAll("-", "~-~");
expression = expression.replaceAll("/+", "~/~");
expression = expression.replaceAll("\\(", "~(~"); //also you can use [(] instead of \\(
expression = expression.replaceAll("\\)", "~)~"); //also you can use [)] instead of \\)
expression = expression.replaceAll("~~", "~");
if(expression.startsWith("~")) {
expression = expression.substring(1);
}


String[] expressionArray = expression.split("~");
System.out.println(Arrays.toString(expressionArray));

下面是一个简单干净的实现,它与Pattern#split一致,并且适用于变长模式,后面的查看不支持,并且更容易使用。它类似于@cletus提供的解决方案

public static String[] split(CharSequence input, String pattern) {
return split(input, Pattern.compile(pattern));
}


public static String[] split(CharSequence input, Pattern pattern) {
Matcher matcher = pattern.matcher(input);
int start = 0;
List<String> result = new ArrayList<>();
while (matcher.find()) {
result.add(input.subSequence(start, matcher.start()).toString());
result.add(matcher.group());
start = matcher.end();
}
if (start != input.length()) result.add(input.subSequence(start, input.length()).toString());
return result.toArray(new String[0]);
}

我在这里不做空检查,Pattern#split没有,为什么我要。我不喜欢结尾的if,但它是与Pattern#split保持一致所必需的。否则,我将无条件地追加,如果输入字符串以模式结束,则结果的最后一个元素将是空字符串。

为了与Pattern#split保持一致,我转换为String[],我使用new String[0]而不是new String[result.size()],参见在这里了解原因。

以下是我的测试:

@Test
public void splitsVariableLengthPattern() {
String[] result = Split.split("/foo/$bar/bas", "\\$\\w+");
Assert.assertArrayEquals(new String[] { "/foo/", "$bar", "/bas" }, result);
}


@Test
public void splitsEndingWithPattern() {
String[] result = Split.split("/foo/$bar", "\\$\\w+");
Assert.assertArrayEquals(new String[] { "/foo/", "$bar" }, result);
}


@Test
public void splitsStartingWithPattern() {
String[] result = Split.split("$foo/bar", "\\$\\w+");
Assert.assertArrayEquals(new String[] { "", "$foo", "/bar" }, result);
}


@Test
public void splitsNoMatchesPattern() {
String[] result = Split.split("/foo/bar", "\\$\\w+");
Assert.assertArrayEquals(new String[] { "/foo/bar" }, result);
}

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

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]

这个问题的一个微妙之处涉及到“前导分隔符”问题:如果要有一个组合的令牌和分隔符数组,则必须知道它是以令牌还是以分隔符开始的。你当然可以假设前导界限应该被丢弃,但这似乎是一个不合理的假设。你可能还想知道你是否有一个拖拽的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" )


}

如果你想保留字符,那么使用带有.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"));
}