切分字符串
入门。
一般的语言都会提供切分字符串的函数,比如把a,b,c
切成a
,b
,和c
:
Java
jshell> "a,b,c".split(",");
$1 ==> String[3] { "a", "b", "c" }
或 Python
>>> "a,b,c".split(",")
['a', 'b', 'c']
放弃?
"a.b.c"
Python 没问题:
>>> "a.b.c".split(".")
['a', 'b', 'c']
Java 好像不太对:
jshell> "a.b.c".split(".");
$2 ==> String[0] { }
"a|b|c"
Python 依然茁壮
>>> 'a|b|c'.split("|")
['a', 'b', 'c']
Java 还是……
jshell> "a|b|c".split("|")
$3 ==> String[5] { "a", "|", "b", "|", "c" }
",,"
Python 再次准确无误的给了我们三个空串:
>>> ",,".split(",")
['', '', '']
Java 却什么都没有
jshell> ",,".split(",")
$3 ==> String[0] { }
"a\b\c"
再来一个 Java 的变态例子:将a\b\c
保存到一个文本文件tmp.txt
中,然后读取它
jshell> String s = Files.readAllLines(Paths.get("tmp.txt")).get(0);
s ==> "a\\b\\c"
文件中的一个\
变成了两个,因为要 escape。那如何 split 这个字符串呢?
jshell> s.split("\")
| Error:
| unclosed string literal
| s.split("\")
|
显然一个\
是肯定不行的。那就两个:
jshell> s.split("\\")
| Exception java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
| \
| at Pattern.error (Pattern.java:2015)
| at Pattern.compile (Pattern.java:1784)
| at Pattern.<init> (Pattern.java:1427)
| at Pattern.compile (Pattern.java:1068)
| at String.split (String.java:2317)
| at String.split (String.java:2364)
| at (#6:1)
进阶!
Java 中的 split 用的是 regex,所以需要转义,比如第一个例子
jshell> "a.b.c".split("\\.")
$4 ==> String[3] { "a", "b", "c" }
注意在转义的时候如果写作\.
,那是在尝试转义.
,必须要两个转义符才能保留下一个\
在字符串里,然后再把\.
放到正则表达式里去转义.
,否则在 regex 里.
表示任意字符。
第二个例子也是一样的:
jshell> "a|b|c".split("\\|")
$5 ==> String[3] { "a", "b", "c" }
第三个例子,是因为所有末尾的空串都被扔掉了。比如
jshell> ",a,,".split(",")
$6 ==> String[2] { "", "a" }
第一个空串被保留了,但a
后面的空串都没了。如果要保留所有的空串,需要将第二个参数设为-1
jshell> ",a,,".split(",", -1)
$7 ==> String[4] { "", "a", "", "" }
最后一个例子,正确的解法是这样的:
jshell> s.split("\\\\")
$8 ==> String[3] { "a", "b", "c" }
没错,一个文件中的\
,要用四个来分解。数数这里 escape 了几次。