之前在http://shukuiyan.iteye.com/blog/507915文中已經(jīng)敘述過這個問題,但是最近一次筆試中居然有碰到了這個知識點戈二,而且還做錯了少辣,囧讲婚!學(xué)藝不精啊另锋。題目大概是這樣的:
String?s2="this?is?a?test";
String?sarray[]=s2.split("/s");
System.out.println("sarray.length="+sarray.length);
這個輸出是什么還是編譯出錯总处?我想那個split方法中的參數(shù)要是"s"的話狈惫,輸出一定是4了,就是將原來字符串分成了數(shù)組{"thi","i","a te","t"}鹦马,但是原題split方法中的參數(shù)要是"/s"胧谈,那么這個參數(shù)到底是嘛意思呢,實驗后輸出結(jié)果居然是1菠红。
原因還得深究啊第岖。
java.lang.string.split,即split 方法试溯,它實現(xiàn)的功能是將一個字符串分割為子字符串蔑滓,然后將結(jié)果作為字符串?dāng)?shù)組返回。 格式為:
stringObj.split([separator遇绞,[limit]])
其中stringObj是必選項键袱,表示要被分解的 String 對象或文字。該對象不會被 split 方法修改摹闽。 separator 為可選項蹄咖,表示字符串或正則表達式對象,它標識了分隔字符串時使用的是一個還是多個字符付鹿。如果忽略該選項澜汤,返回包含整個字符串的單一元素數(shù)組。 limit 為可選項舵匾,該值用來限制返回數(shù)組中的元素個數(shù)俊抵。 值得注意的是: split 方法的結(jié)果是一個字符串?dāng)?shù)組,在 stingObj 中每個出現(xiàn) separator 的位置都要進行分解坐梯,separator 不作為任何數(shù)組元素的部分返回徽诲。
一個例子
String?srcstring="this?is?a?about?split?test";
String?stringarray[]=srcstring.split("?");
////?在每個空格字符處進行分解
for(String?stemp:stringarray){
System.out.println(stemp);
}
String?srcstring1="?this??is?a?about?split??test";//有n個空格的話,分成的數(shù)組長度為n+1
//如果字符串中有多個空格時,則兩個空格間認為是沒有字符谎替,結(jié)果字符串?dāng)?shù)組中該位置為空偷溺。
String?stringarray1[]=srcstring1.split("?");
for(String?stemp:stringarray1){
System.out.println(stemp);
}
這樣輸出結(jié)果為
this
is
a
about
split
test
另一個:
this
is
a
about
split
test
另外一個例子
String?srcstring="this?is?a?about?split?test";
String?stringarray[]=srcstring.split("?",2);
////?在每個空格字符處進行分解
for(String?stemp:stringarray){
System.out.println(stemp);
}
輸出結(jié)果為
this
is?a?about?split?test
看看下面這個
String?ipstring="59.64.159.224";
String?iparray[]=ipstring.split(".");
for(String?stemp:iparray){
System.out.println(stemp);
}
這個輸出為空,為什么呢钱贯?
因為 public string[] split(string regex) 這里的參數(shù)的名稱是regex 挫掏,也就是 regular expression (正則表達式)。這個參數(shù)并不是一個簡單的分割用的字符喷舀,而是一個正則表達式砍濒,以下是split 方法的實現(xiàn)代碼:
public string[] split(string regex, int limit) {
return pattern.compile(regex).split(this, limit);
}
split 的實現(xiàn)直接調(diào)用的 matcher 類的 split 的方法淋肾。我們知道硫麻,“ . ”在正則表達式中有特殊的含義,因此我們使用的時候必須進行轉(zhuǎn)義樊卓。 只要將
String?iparray[]=ipstring.split(".");
改為
String?iparray[]=ipstring.split("\\.");
就可以了拿愧。
那么這里在列上一些轉(zhuǎn)義字符
\\反斜杠
\t間隔('\u0009')
\n換行('\u000A')
\r回車('\u000D')
\d數(shù)字等價于[0-9]
\D非數(shù)字等價于[^0-9]
\s空白符號[\t\n\x0B\f\r]
\S非空白符號[^\t\n\x0B\f\r]
\w單獨字符[a-zA-Z_0-9]
\W非單獨字符[^a-zA-Z_0-9]
\f換頁符
\e Escape
\b一個單詞的邊界
\B一個非單詞的邊界
\G前一個匹配的結(jié)束
注意:public String[] split(String regex,int limit)根據(jù)匹配給定的正則表達式來拆分此字符串。
此方法返回的數(shù)組包含此字符串的每個子字符串碌尔,這些子字符串由另一個匹配給定的表達式的子字符串終止或由字符串結(jié)束來終止浇辜。數(shù)組中的子字符串按它們在此字符串中的順序排列。如果表達式不匹配輸入的任何部分唾戚,則結(jié)果數(shù)組只具有一個元素柳洋,即此字符串。
limit 參數(shù)控制模式應(yīng)用的次數(shù)叹坦,因此影響結(jié)果數(shù)組的長度熊镣。如果該限制 n 大于 0,則模式將被最多應(yīng)用 n - 1 次募书,數(shù)組的長度將不會大于 n绪囱,而且數(shù)組的最后項將包含超出最后匹配的定界符的所有輸入。如果 n 為非正莹捡,則模式將被應(yīng)用盡可能多的次數(shù)鬼吵,而且數(shù)組可以是任意長度。如果 n 為零篮赢,則模式將被應(yīng)用盡可能多的次數(shù)齿椅,數(shù)組可有任何長度,并且結(jié)尾空字符串將被丟棄启泣。
回到最初的題目涣脚,題目中給出的匹配正則表達式為"/s",表示空白字符种远,此時給定的字符串中沒有匹配的字符涩澡,則輸出為原字符串,所以輸出的字符長度為1.
再附上一些關(guān)于java中正則表達式的知識吧
^為限制開頭
^java條件限制為以Java為開頭字符
$為限制結(jié)尾
java$條件限制為以java為結(jié)尾字符
.條件限制除\n以外任意一個單獨字符
java..條件限制為java后除換行外任意兩個字符
加入特定限制條件「[]」
[a-z]條件限制在小寫a to z范圍中一個字符
[A-Z]條件限制在大寫A to Z范圍中一個字符
[a-zA-Z]條件限制在小寫a to z或大寫A to Z范圍中一個字符
[0-9]條件限制在小寫0 to 9范圍中一個字符
[0-9a-z]條件限制在小寫0 to 9或a to z范圍中一個字符
[0-9[a-z]]條件限制在小寫0 to 9或a to z范圍中一個字符(交集)
[]中加入^后加再次限制條件「[^]」
[^a-z]條件限制在非小寫a to z范圍中一個字符
[^A-Z]條件限制在非大寫A to Z范圍中一個字符
[^a-zA-Z]條件限制在非小寫a to z或大寫A to Z范圍中一個字符
[^0-9]條件限制在非小寫0 to 9范圍中一個字符
[^0-9a-z]條件限制在非小寫0 to 9或a to z范圍中一個字符
[^0-9[a-z]]條件限制在非小寫0 to 9或a to z范圍中一個字符(交集)
在限制條件為特定字符出現(xiàn)0次以上時,可以使用「*」
J* ??? 0個以上J
.* ??? 0個以上任意字符
J.*D ??? J與D之間0個以上任意字符
在限制條件為特定字符出現(xiàn)1次以上時妙同,可以使用「+」
J+ ??? 1個以上J
.+ ??? 1個以上任意字符
J.+D ??? J與D之間1個以上任意字符
在限制條件為特定字符出現(xiàn)有0或1次以上時射富,可以使用「?」
JA? ??? J或者JA出現(xiàn)
限制為連續(xù)出現(xiàn)指定次數(shù)字符「{a}」
J{2} ??? JJ
J{3} ??? JJJ
文字a個以上,并且「{a,}」
J{3,} ??? JJJ,JJJJ,JJJJJ,???(3次以上J并存)
文字個以上粥帚,b個以下「{a,b}」
J{3,5} ??? JJJ或JJJJ或JJJJJ
兩者取一「|」
J|A ??? J或A
Java|Hello ??? Java或Hello
「()」中規(guī)定一個組合類型
比如胰耗,我查詢index中間的數(shù)據(jù),可寫作(.+?)
在使用Pattern.compile函數(shù)時芒涡,可以加入控制正則表達式的匹配行為的參數(shù):
Pattern Pattern.compile(String regex, int flag)
flag的取值范圍如下:
Pattern.CANON_EQ當(dāng)且僅當(dāng)兩個字符的"正規(guī)分解(canonical decomposition)"都完全相同的情況下柴灯,才認定匹配。比如用了這個標志之后费尽,表達式"a\u030A"會匹配"?"赠群。默認情況下,不考慮"規(guī)范相等性(canonical equivalence)"旱幼。
Pattern.CASE_INSENSITIVE(?i)默認情況下查描,大小寫不明感的匹配只適用于US-ASCII字符集。這個標志能讓表達式忽略大小寫進行匹配柏卤。要想對Unicode字符進行大小不明感的匹配冬三,只要將UNICODE_CASE與這個標志合起來就行了。
Pattern.COMMENTS(?x)在這種模式下缘缚,匹配時會忽略(正則表達式里的)空格字符(譯者注:不是指表達式里的"\\s"勾笆,而是指表達式里的空格,tab桥滨,回車之類)窝爪。注釋從#開始,一直到這行結(jié)束该园∷嵘幔可以通過嵌入式的標志來啟用Unix行模式。
Pattern.DOTALL(?s)在這種模式下里初,表達式'.'可以匹配任意字符啃勉,包括表示一行的結(jié)束符。默認情況下双妨,表達式'.'不匹配行的結(jié)束符淮阐。
Pattern.MULTILINE
(?m)在這種模式下,'^'和'$'分別匹配一行的開始和結(jié)束刁品。此外泣特,'^'仍然匹配字符串的開始,'$'也匹配字符串的結(jié)束挑随。默認情況下状您,這兩個表達式僅僅匹配字符串的開始和結(jié)束。
Pattern.UNICODE_CASE
(?u)在這個模式下,如果你還啟用了CASE_INSENSITIVE標志膏孟,那么它會對Unicode字符進行大小寫不明感的匹配眯分。默認情況下,大小寫不敏感的匹配只適用于US-ASCII字符集柒桑。
Pattern.UNIX_LINES(?d)在這個模式下弊决,只有'\n'才被認作一行的中止,并且與'.'魁淳,'^'飘诗,以及'$'進行匹配。
拋開空泛的概念界逛,下面寫出幾個簡單的Java正則用例:
◆比如昆稿,在字符串包含驗證時
//查找以Java開頭,任意結(jié)尾的字符串
Pattern pattern = Pattern.compile("^Java.*");
Matcher matcher = pattern.matcher("Java不是人");
boolean b= matcher.matches();
//當(dāng)條件滿足時,將返回true仇奶,否則返回false
System.out.println(b);
◆以多條件分割字符串時
Pattern pattern = Pattern.compile("[, |]+");
String[] strs = pattern.split("Java Hello World? Java,Hello,,World|Sun");
for (int i=0;i
System.out.println(strs[i]);
}
◆文字替換(首次出現(xiàn)字符)
Pattern pattern = Pattern.compile("正則表達式");
Matcher matcher = pattern.matcher("正則表達式Hello World,正則表達式Hello World");
//替換第一個符合正則的數(shù)據(jù)
System.out.println(matcher.replaceFirst("Java"));
◆文字替換(全部)
Pattern pattern = Pattern.compile("正則表達式");
Matcher matcher = pattern.matcher("正則表達式Hello World,正則表達式Hello World");
//替換第一個符合正則的數(shù)據(jù)
System.out.println(matcher.replaceAll("Java"));
◆文字替換(置換字符)
Pattern pattern = Pattern.compile("正則表達式");
Matcher matcher = pattern.matcher("正則表達式Hello World,正則表達式Hello World ");
StringBuffer sbr = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sbr, "Java");
}
matcher.appendTail(sbr);
System.out.println(sbr.toString());
◆驗證是否為郵箱地址
String str="ceponline@yahoo.com.cn";
Pattern pattern = Pattern.compile("[\\w\\.\\-]+@([\\w\\-]+\\.)+[\\w\\-]+",Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
System.out.println(matcher.matches());
◆去除html標記
Pattern pattern = Pattern.compile("<.+?>", Pattern.DOTALL);
Matcher matcher = pattern.matcher("主頁");
String string = matcher.replaceAll("");
System.out.println(string);
◆查找html中對應(yīng)條件字符串
Pattern pattern = Pattern.compile("href=\"(.+?)\"");
Matcher matcher = pattern.matcher("主頁");
if(matcher.find())
System.out.println(matcher.group(1));
}
◆截取http://地址
//截取url
Pattern pattern = Pattern.compile("(http://|https://){1}[\\w\\.\\-/:]+");
Matcher matcher = pattern.matcher("dsdsdsfdf");
StringBuffer buffer = new StringBuffer();
while(matcher.find()){
buffer.append(matcher.group());
buffer.append("\r\n");
System.out.println(buffer.toString());
}
◆替換指定{}中文字
String str = "Java目前的發(fā)展史是由{0}年-{1}年";
String[][] object={new String[]{"\\{0\\}","1995"},new String[]{"\\{1\\}","2007"}};
System.out.println(replace(str,object));
public static String replace(final String sourceString,Object[] object) {
String temp=sourceString;
for(int i=0;i
String[] result=(String[])object[i];
Pattern??? pattern = Pattern.compile(result[0]);
Matcher matcher = pattern.matcher(temp);
temp=matcher.replaceAll(result[1]);
}
return temp;
}
◆以正則條件查詢指定目錄下文件
//用于緩存文件列表
private ArrayList files = new ArrayList();
//用于承載文件路徑
private String _path;
//用于承載未合并的正則公式
private String _regexp;
class MyFileFilter implements FileFilter {
/**
*匹配文件名稱
*/
public boolean accept(File file) {
try {
Pattern pattern = Pattern.compile(_regexp);
Matcher match = pattern.matcher(file.getName());
return match.matches();
} catch (Exception e) {
return true;
}
}
}
/**
*解析輸入流
* @param inpu