JAVA中正則表達式使用介紹
一、什么是正則表達式
正則表達式是一種可以用于模式匹配和替換的強有力的工具。我們可以在幾乎所有的基于UNIX系統(tǒng)的工具中找到正則表達式的身影,例如,vi編輯器,Perl或PHP腳本語言,以及awk或sed shell程序等。此外,象JavaScript這種客戶端的腳本語言也提供了對正則表達式的支持。
正則表達式可以讓用戶通過使用一系列的特殊字符構建匹配模式,進行信息的驗證。
此外,它還能夠高效地創(chuàng)建、比較和修改字符串,以及迅速地分析大量文本和數(shù)據(jù)以搜索、移除和替換文本。
例如:
二、基礎知識
1.1 開始、結束符號(它們同時也屬于定位符)
我們先從簡單的開始。假設你要寫一個正則表達式規(guī)則,你會用到 ^ 和 $ 符號,他們分別是行首符、行尾符。
例如:/^\d+[0-9]?\d+$/
1.2 句點符號
假設你在玩英文拼字游戲,想要找出三個字母的單詞,而且這些單詞必須以“t”字母開頭,以“n”字母結束。另外,假設有一本英文字典,你可以用正則表達式搜索它的全部內(nèi)容。要構造出這個正則表達式,你可以使用一個通配符——句點符號“.”。這樣,完整的表達式就是“t.n”,它匹配“tan”、“ten”、“tin”和“ton”,還匹配“t#n”、“tpn”甚至“t n”,還有其他許多無意義的組合。這是因為句點符號匹配所有字符,包括空格、Tab字符甚至換行符:
1.3 方括號符號
為了解決句點符號匹配范圍過于廣泛這一問題,你可以在方括號(“[]”)里面指定看來有意義的字符。此時,只有方括號里面指定的字符才參與匹配。也就是說,正則表達式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”。但“Toon”不匹配,因為在方括號之內(nèi)你只能匹配單個字符:
1.4 “或”符號
如果除了上面匹配的所有單詞之外,你還想要匹配“toon”,那么,你可以使用“|”操作符。“|”操作符的基本意義就是“或”運算。要匹配“toon”,使用“t(a|e|i|o|oo)n”正則表達式。這里不能使用方擴號,因為方括號只允許匹配單個字符;這里必須使用圓括號“()”。
1.5 表示匹配次數(shù)的符號
表一:顯示了表示匹配次數(shù)的符號,這些符號用來確定緊靠該符號左邊的符號出現(xiàn)的次數(shù):
代碼/語法 |
說明 |
* |
重復零次或更多次 |
+ |
重復一次或更多次 |
? |
重復零次或一次 |
{n} |
重復n次 |
{n,} |
重復n次或更多次 |
{n,m} |
重復n到m次 |
表二:常用符號
代碼/語法 |
相當于 |
\w |
[0-9A-Za-z_] |
\W |
[^0-9A-Za-z_] |
\s |
[\t\n\r\f] |
\S |
[^\t\n\r\f] |
\d |
[0-9] |
\D |
[^0-9] |
表二中的符號意義:
· \w
包括下劃線的字母和數(shù)字。等同于[0-9A-Za-z_]
。
若為匹配多字節(jié)字符的正則表達式時,則也會匹配日語的全角字符。
· \W
非字母和數(shù)字。\w
以外的單個字符。
· \s
空字符。相當于[ \t\n\r\f]
· \S
非空字符。[ \t\n\r\f]
以外的單個字符。
· \d
數(shù)字。即[0-9]
· \D
非數(shù)字。\d以外的單個字符
1.6 定位符介紹(用于規(guī)定匹配模式在目標對象中的出現(xiàn)位置)
較為常用的定位符包括: “^”, “$”, “\b” 以及 “\B”。其中,“^”定位符規(guī)定匹配模式必須出現(xiàn)在目標字符串的開頭,“$”定位符規(guī)定匹配模式必須出現(xiàn)在目標對象的結尾,\b定位符規(guī)定匹配模式必須出現(xiàn)在目標字符串的開頭或結尾的兩個邊界之一,而“\B”定位符則規(guī)定匹配對象必須位于目標字符串的開頭和結尾兩個邊界之內(nèi),即匹配對象既不能作為目標字符串的開頭,也不能作為目標字符串的結尾。同樣,我們也可以把“^”和“$”以及“\b”和“\B”看作是互為逆運算的兩組定位符。舉例來說:
/^hell/
因為上述正則表達式中包含“^”定位符,所以可以與目標對象中以 “hell”, “hello”或 “hellhound”開頭的字符串相匹配。
/ar$/
因為上述正則表達式中包含“$”定位符,所以可以與目標對象中以 “car”, “bar”或 “ar” 結尾的字符串相匹配。
/\bbom/
因為上述正則表達式模式以“\b”定位符開頭,所以可以與目標對象中以 “bomb”, 或 “bom”開頭的字符串相匹配。
/man\b/
因為上述正則表達式模式以“\b”定位符結尾,所以可以與目標對象中以 “human”, “woman”或 “man”結尾的字符串相匹配。
為了能夠方便用戶更加靈活的設定匹配模式,正則表達式允許使用者在匹配模式中指定某一個范圍而不局限于具體的字符。例如:
/[A-Z]/
上述正則表達式將會與從A到Z范圍內(nèi)任何一個大寫字母相匹配。
/[a-z]/
上述正則表達式將會與從a到z范圍內(nèi)任何一個小寫字母相匹配。
/[0-9]/
上述正則表達式將會與從0到9范圍內(nèi)任何一個數(shù)字相匹配。
/([a-z][A-Z][0-9])+/
上述正則表達式將會與任何由字母和數(shù)字組成的字符串,如 “aB0” 等相匹配。這里需要提醒用戶注意的一點就是可以在正則表達式中使用 “()” 把字符串組合在一起。“()”符號包含的內(nèi)容必須同時出現(xiàn)在目標對象中。因此,上述正則表達式將無法與諸如 “abc”等的字符串匹配,因為“abc”中的最后一個字符為字母而非數(shù)字。
如果我們希望在正則表達式中實現(xiàn)類似編程邏輯中的“或”運算,在多個不同的模式中任選一個進行匹配的話,可以使用管道符 “|”。例如:
/to|too|2/
上述正則表達式將會與目標對象中的 “to”, “too”, 或 “2” 相匹配。
正則表達式中還有一個較為常用的運算符,即否定符 “[^]”。與我們前文所介紹的定位符 “^” 不同,否定符 “[^]”規(guī)定目標對象中不能存在模式中所規(guī)定的字符串。例如:
/[^A-C]/
上述字符串將會與目標對象中除A,B,和C之外的任何字符相匹配。一般來說,當“^”出現(xiàn)在 “[]”內(nèi)時就被視做否定運算符;而當“^”位于“[]”之外,或沒有“[]”時,則應當被視做定位符。
最后,當用戶需要在正則表達式的模式中加入元字符,并查找其匹配對象時,可以使用轉義符“\”。例如:
/Th\*/
上述正則表達式將會與目標對象中的“Th*”而非“The”等相匹配。
三、正則表達式規(guī)則的例子
/^(\d{3}-|\d{4}-)?(\d{8}|\d{7})?$/ //國內(nèi)電話
/^[1-9]*[1-9][0-9]*$/ //騰訊QQ
/^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$/ //email地址
/^[a-zA-Z]+://(\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*(\\?\\s*)?$/ //url
/^\d+$/ //非負整數(shù)
/^[0-9]*[1-9][0-9]*$/ //正整數(shù)
/^((-\\d+)|(0+))$/ //非正整數(shù)
/^-[0-9]*[1-9][0-9]*$/ //負整數(shù)
/^-?\\d+$/ //整數(shù)
/^\\d+(\\.\\d+)?$/ //非負浮點數(shù)
/^(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*))$/ //正浮點數(shù)
/^((-\\d+(\\.\\d+)?)|(0+(\\.0+)?))$/ //非正浮點數(shù)
/^(-(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/ //負浮點數(shù)
/^(-?\\d+)(\\.\\d+)?$/ //浮點數(shù)
/^[a-zA-Z]+$/ //由26個英文字母組成的字符串
/^[a-z]+$/ //由26個英文字母的大寫組成的字符串
/^[a-z]+$/ //由26個英文字母的小寫組成的字符串
/^[a-za-z0-9]+$/ //由數(shù)字和26個英文字母組成的字符串
/^\\w+$/ //由數(shù)字、26個英文字母或者下劃線組成的字符串
/^\d+[.]?\d+$/ //可以有小數(shù)點的任意多數(shù)字(全部為數(shù)字)
/(?=^[0-9a-zA-Z]{4,20}$)\w*[a-zA-Z]+\w*/ //同時滿足下面三個條件
(1) 數(shù)字和字母(2)4-20位(3)不能全部是數(shù)字
四、應用
1.應用于JavaScript (用來驗證)
function doCheck(){
var patrn = /^\d+[.]?\d+$/;
var vf1 = document.queryForm.f2Text.value; //文本框
var vf2 = document.queryForm.f4Text.value;
var vf3 = document.queryForm.f6Text.value;
var va1 = document.queryForm.a2.checked; //單選按鈕
var va2 = document.queryForm.a4.checked;
var va3 = document.queryForm.a6.checked;
if(va1){
if(!patrn.exec(vf1)){
alert("請您輸入數(shù)字,如:30 、 5.8");
return;
}
}
if(va2){
if(!patrn.exec(vf2)){
alert("請您輸入數(shù)字,如:30 、 5.8");
return;
}
}
。。。 。。。
}
2.在Java中的應用
Java包java.util.regex提供對正則表達式的支持。而且Java.lang.String類中的replaceAll和split函數(shù)也是調(diào)用的正則表達式來實現(xiàn)的。
正則表達式對字符串的操作主要包括:字符串匹配,指定字符串替換,指定字符串查找和字符串分割。下面就用一個例子來說明這些操作是如何實現(xiàn)的:
<%@ page import="java.util.regex.*"%>;
<%
Pattern p=null; //正則表達式
Matcher m=null; //操作的字符串
boolean b;
String s=null;
StringBuffer sb=null;
int i=0;
//字符串匹配,這是不符合的
p = Pattern.compile("a*b");
m = p.matcher("baaaaab");
b = m.matches();
out.println(b+"<br>;");
//字符串匹配,這是符合的
p = Pattern.compile("a*b");
m = p.matcher("aaaaab");
b = m.matches();
out.println(b+"<br>;");
//字符串替換
p = Pattern.compile("ab");
m = p.matcher("aaaaab");
s = m.replaceAll("d");
out.println(s+"<br>;");
p = Pattern.compile("a*b");
m = p.matcher("aaaaab");
s = m.replaceAll("d");
out.println(s+"<br>;");
p = Pattern.compile("a*b");
m = p.matcher("caaaaab");
s = m.replaceAll("d");
out.println(s+"<br>;");
//字符串查找
p = Pattern.compile("cat");
m = p.matcher("one cat two cats in the yard");
sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "dog");
i++;
}
m.appendTail(sb);
out.println(sb.toString()+"<br>;");
out.println(i+"<br>;");
i=0;
p = Pattern.compile("cat");
m = p.matcher("one cat two ca tsi nthe yard");
sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "dog");
i++;
}
m.appendTail(sb);
out.println(sb.toString()+"<br>;");
out.println(i+"<br>;");
p = Pattern.compile("cat");
m = p.matcher("one cat two cats in the yard");
p=m.pattern();
m = p.matcher("bacatab");
b = m.matches();
out.println(b+"<br>;");
s = m.replaceAll("dog");
out.println(s+"<br>;");
i=0;
p = Pattern.compile("(fds){2,}");
m = p.matcher("dsa da fdsfds aaafdsafds aaf");
sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "dog");
i++;
}
m.appendTail(sb);
out.println(sb.toString()+"<br>;");
out.println(i+"<br>;");
p = Pattern.compile("cat");
m = p.matcher("one cat two cats in the yard");
sb = new StringBuffer();
while (m.find()) {
m.appendReplacement(sb, "<font color=\"red\">;cat</font>;");
}
m.appendTail(sb);
out.println(sb.toString()+"<br>;");
String aa=sb.toString();
out.println(aa+"<br>;");
//字符串分割
p = Pattern.compile("a+");
String[] a=p.split("caaaaaat");
for(i=0;i<a.length;i++)
{
out.println(a+"<br>;");
}
p = Pattern.compile("a+");
a=p.split("c aa aaaa t",0);
for(i=0;i<a.length;i++)
{
out.println(a+"<br>;");
}
p = Pattern.compile(" +");
a=p.split("c aa aaaa t",0);
for(i=0;i<a.length;i++)
{
out.println(a+"<br>;");
}
p = Pattern.compile("\\+");
a=p.split("dsafasdfdsafsda+dsagfasdfa+sdafds");
out.println(a.length+"<br>;");
for(i=0;i<a.length;i++)
{
out.println(a+"<br>;");
}