Java與正則表達式
標簽: Java基礎
正則
正如
正則
的名字所顯示的是描述了一個規則
, 通過這個規則去匹配字符串
. 學習正則就是學習正則表達式的語法規則
正則語法
普通字符
字母, 數字, 漢字, 下劃線, 以及沒有特殊定義的標點符號都是普通字符
. 表達式中的普通字符在匹配一個字符串時, 匹配與之相同的一個字符.
轉義字符
字符 | 解釋 |
---|---|
\n |
換行符 |
\t |
制表符 |
\^ \$ \( \) \{ \} \? \+ \* | \\ \[ \] |
匹配這些字符本身 |
標準字符集合
字符 | 匹配 |
---|---|
\d |
任意一個數字 |
\w |
任意一個字母/數字/下劃線 |
\s |
任意一個空格/制表符/換行符等空白字符 |
. |
小數點在內的任意一個字符(除\n 外) |
[\s\S] |
匹配\n 在內的任意一個字符 |
- 注意大小寫: 大寫是取反
自定義字符集合
[]
方括號匹配方式, 能夠匹配方括號中的任意一個字符.
表達式 | 解釋 |
---|---|
[ab5@v] |
匹配a b 5 @ v 中任意一個 |
[^ab5@v] |
匹配a b 5 @ v 之外任意一個 |
[f-k] |
匹配f-k 之間任意一個字母 |
[^f-k] |
匹配f-k 之外任意一個 |
[f-k0-3] |
匹配f-k 或0-3 之間任意一個字母 |
[^f-k0-3] |
不匹配f-k 或0-3 之間任意一個字母 |
注:
- 正則表達式中的特殊符號, 被包含到
[]
中, 則失去特殊意義, 除了-
^
之外.
[]
中的^
表示取反的含義.[]
中的-
表示范圍的含義
- 標準字符集合(除小數點外),如果被包含于中括號中,則自定義集合將包含該集合.
如[\d.\-+]
將匹配: 數字, 小數點,-
,+
量詞
量詞 | 解釋 |
---|---|
{n} |
表達式重復n次 |
{m,n} |
表達式至少重復m次,最多重復n次 |
{m,} |
表達式至少重復m次 |
? |
匹配表達式0次或者1次 |
+ |
表達式至少出現1次,相當于 {1,} |
* |
表達式不出現或出現任意次,相當于 {0,} |
-
貪婪模式與非貪婪模式
貪婪模式: 匹配字符越多越好,默認
.
非貪婪模式: 匹配字符越少越好, 需要在量詞后再加上一個?
號. -
示例
- 匹配手機號
1[358]\d{9}
- 匹配郵箱
([\w\-\.]+)@([0-9a-zA-Z\-]+)(\.[a-zA-Z]{2,4}){1,2}
- 匹配手機號
字符邊界
零寬匹配: 匹配的不是字符而是位置(符合某種條件的位置),不匹配任何字符.
字符 | 解釋 |
---|---|
^ |
與字符串開始的地方匹配 |
$ |
與字符串結束的地方匹配 |
\b |
匹配一個單詞邊界,也就是單詞和空格之間的位置 |
注: \b
會匹配這樣一個位置: 前面的字符與后面的字符不全是\w
選擇符與分組
表達式 | 解釋 |
---|---|
| |
左右兩邊表達式之間 “或” 關系,匹配左邊或右邊 |
() 捕獲組 |
被修飾時,() 中的表達式可以作為整體被修飾; 取匹配結果時, () 中的表達式匹配到的內容可以被單獨得到; 每一對括號會被分配一個編號(以( 為準,從左到右: 從1開始) |
(?:exp) 非捕獲組 |
一些表達式中, 不得不使用() , 但又不需保存() 中子表達式匹配的內容, 這時可以使用非捕獲組來抵消() 帶來的副作用 |
注: 非捕獲組可以用于當處理大量文本時用于優化內存分配.
- 反引用
\nnn
由上面可知, 捕獲組默認被分配了編號, 通過反向引用, 可以對分組已捕獲的字符串進行引用 - 示例
(\w{2})\1
匹配類似toto
dodo
gogo
這樣由一個單詞復制而來得到的字符串
(img)\w+\1
匹配前后都是img的字符串
零寬斷言(預搜索)
- 零寬度: 只進行子表達式的匹配, 匹配內容不計入最終的匹配結果.
- 位置匹配: 判斷當前位置的前后字符是否符合指定的條件, 但不保留前后的字符.
正則表達式中, 如果子表達式匹配到得是字符內容, 而非位置, 并被保留到最終的匹配結果中, 那么就認為這個子表達式是
占有字符
的; 如果子表達式匹配的僅僅是位置, 或者匹配的內容并不保存到最終的匹配結果中, 那么就認為這個子表達式是零寬度
的(占有字符或零寬度, 是針對匹配的內容是否保留到最終結果而言的)
表達式 | 解釋 |
---|---|
(?=exp) |
斷言自身出現的位置的后面能夠 匹配表達式exp |
(?!exp) |
斷言自身出現的位置的后面不能 匹配表達式exp |
(?<=exp) |
斷言自身出現的位置的前面能夠 匹配表達式exp |
(?<\!exp) |
斷言自身出現的位置的前面不能 匹配表達式exp |
- 示例
[a-z]+(?=ing)
匹配所有以ing結尾的單詞, 但ing并不放入字符串
[a-z]+(?=\d+)
匹配所有以數字結尾的單詞
[a-z]+(?!\d+)
匹配不以數字結尾的單詞
(?<=(href=\"))
匹配以href="
開頭的字符串
Java Pattern與Matcher
java.util.regex
包下提供的Pattern
與Matcher
兩個類提供了在Java中的正則支持;Pattern
對象是正則表達式編譯后在內存中的表現形式, 因此, 正則表達式字符串必須先被編譯為Pattern對象Pattern pattern = Pattern.compile("\\w+");
然后再利用該Pattern對象創建對象的Matcher對象Matcher matcher = pattern.matcher(input);
.Matcher
對象是一個對CharSequence
執行匹配操作的正則引擎: 執行匹配所涉及的狀態保留在Matcher對象中, 多個Matcher對象可共享同一個Pattern對象.
/** * Created by jifang on 15/12/15. */ public class LearnRegexp { @Test public void testSearch() { String input = "hello1997&&2000"; // 將一個正則表達式編譯成Pattern對象 Pattern pattern = Pattern.compile("\\w+"); Matcher matcher = pattern.matcher(input); // matches嘗試將整個字符序列與該模式匹配 System.out.println(matcher.matches()); // reset將matcher中的指針重新定位 matcher.reset(); // find 方法掃描整個字符串, 查找能否找到下一個符合該模式字符串 while (matcher.find()) { String group = matcher.group(); System.out.println(group); } } /** * 將所有的數字都替換成'#' */ @Test public void testReplace() { String input = "1j2h3h4g5o"; Matcher replace = Pattern.compile("[0-9]").matcher(input); input = replace.replaceAll("#"); System.out.println(input); } /** * 將字符串按數字分割 */ @Test public void testSplit() { String input = "1j24h356h467g589o"; String[] strings = input.split("\\d+"); for (String str : strings) { System.out.println(str); } } }
由上例可以看到: 其實String
中某些方法也支持正則表達式, 如split, replace等(Pattern,Matcher與String的其他用法請參考JDK文檔).
小實驗-抓取網頁中所有的超鏈接
/** * 模仿網絡爬蟲, 抓取網站html, 將里面所有的超鏈接都分析出來 * Created by jifang on 15/12/15. */ public class HtmlAnalyzer { private final String FILE_PATH = "/Users/jifang/save.txt"; @Test public void client() throws IOException { String html = downloadHtml("http://www.163.com/", "gbk"); // (?<=(href=\"))(?:[\w.\/\:\?\=\&]+)(?=\") 匹配url的正則 Set<String> urlSet = analyzeHtml(html, "(?<=(href=\\\"))(?:[\\w.\\/\\:\\?\\=\\&]+)(?=\\\")"); saveToFile(urlSet); System.out.println(); } private String downloadHtml(String url, String charset) throws IOException { URL readUrl = new URL(url); BufferedReader reader = new BufferedReader(new InputStreamReader(readUrl.openStream(), charset)); return CharStreams.toString(reader); } private Set<String> analyzeHtml(String html, String regex) { Set<String> urlSet = new HashSet<>(); // 匹配url的正則表達式 Matcher matcher = Pattern.compile(regex).matcher(html); while (matcher.find()) { String group = matcher.group(); urlSet.add(group); } return urlSet; } private void saveToFile(Set<String> urlSet) throws IOException { PrintStream printer = new PrintStream(new FileOutputStream(FILE_PATH)); for (String url : urlSet) { printer.println(url); } printer.flush(); printer.close(); } }
- 附- 運行上程序需要在pom.xml中添加以下依賴
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>18.0</version> </dependency>
推薦幾個正則驗證工具:
- Mac端: RegExRX
- Win端: RegexBuddy
- Web端: 在線正則表達式測試
參考
來自: http://blog.csdn.net/zjf280441589/article/details/50450169
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!