在做一个题的时候, 要把一串字符串dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext
按\n分割
粘贴到idea, idea识别自动转义成(也是一个坑): "dir\\n\\tsubdir1\\n\\tsubdir2\\n\\t\\tfile.ext"
但是我用
str.split("\n")
str.split("\\\n")
str.split("\\\\\n")
都没有获取到,str.split(“\\\\n”)才获取到了
首先斜杆的特性
\
单个斜杆, 会被视为转义字符
\n
单个斜杆加特点字符, 视为一个字符
\\
两个斜杆在一起, 会视为一个普通的斜杆,无转义效果
其实很多斜杠搞得人云里雾里的关键, 是忽略了个问题: jvm会编译识别一次, 正则解析的时候会识别第二次.
首先看看我们敲得字符串比如4个斜杆a\\\\n
, 到正则解析的过程(为了方便解释,转义后的普通斜杆用中划线代替):
编辑器里: a\\\\n
----> 程序运行: a--n
----> 正则识别到--
即\\
, 同样变成普通斜杆-
: a-n
,即a\n
回过头在看上面的问题,编辑器帮我转义后文本是这样"dir\\n\\tsubdir1\\n\\tsubdir2\\n\\t\\tfile.ext"
, 进入jvm后字符串变"dir-n-tsubdir1-n-tsubdir2-n-t-tfile.ext
(-表示普通的斜杆), 自然也就是四个斜杠才能split了
这里split用Pattern.compile是一样的, split方法里面有一些优化, 对一些regex进行了处理
@Test
public void fun01(){
String str = "a\nbb\\nccc\\\ndddd\\\\neeee";
System.out.println("str = " + str);
/*
print打印结果: 其实这个字符串是有换行的
a
bb\ccc\
dddd\\neeee
*/
String[] ss = str.split("\n"); //["a", "bb\nccc\", "dddd\\neeee"]
String[] ss1 = str.split("\\n"); //["a", "bb\nccc\", "dddd\\neeee"]
String[] ss2 = str.split("\\\n"); //["a", "bb\nccc\", "dddd\\neeee"]
String[] ss3 = str.split("\\\\n"); //["a\nbb", "ccc\\ndddd\", "eeee"]
String str1 = "\\nada";
System.out.println(str1.startsWith("\n")); //F
System.out.println(str1.startsWith("\\n")); //T
System.out.println(str1.startsWith("\\\n")); //F
System.out.println(str1.startsWith("\\\\n")); //F
}
分别解释下4个split:
为了方便理解, 用-
表示普通斜杆,用@
表示换行符\n
首先看看str, 单个\n
,进入jvm识别成单个回车字符@
, \\n
进入jvm识别成-n
,\\\n
识别成-@
, \\\\n
识别成--n
. 注意这里只是说jvm后的字符串. 最后文本在jvm中是:
a@bb-nccc-@dddd--neeee
第一个, 正则解析为@
, 和@
的文本匹配切割
正则解析-n
为@
, 匹配和第一个一样
正则解析-@
,即\回车
, 正则无视第一个斜杆, 并且编译器提示remove redundant escape
, 因此对于正则来说, 给我一个斜杆+回车, 无法组成一个正则表达式, 所以无视第一个斜杆, 结果和第一个一样
正则解析--n
为-n
, 和\\n
的文本匹配切割
顺便说下, startWith, 只收到jvm编译的转义影响, 不受转义的影响