在做一个题的时候, 要把一串字符串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编译的转义影响, 不受转义的影响