国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Merlin的魔力:用新的正則表達式庫解析字符序列

2019-11-18 14:49:35
字體:
來源:轉載
供稿:網友

雖然 java 語言以前的版本支持模式匹配,但 StreamTokenizer 和 StringTokenizer 類卻很少涉及用模式能夠實現的功能。Java 1.4(以及現在的 1.4.1)發行版在 java.util.regex 包中加入了對使用正則表達式的模式匹配的支持。在 Merlin 的魔力系列的這篇文章中,John Zukowski 向您展示了如何用新的正則表達式庫解析字符序列,從而使搜索模式的功能更加強大。
解析模式的文本字符串
正則表達式是根據文本匹配模式的方法 ? 類似于編譯器生成類文件的工作原理。編譯器在源代碼中查找各種模式以便將源代碼表達式轉換為字節碼。通過識別這些源代碼模式,編譯器能夠只將有效的源代碼表示轉換為已編譯的類文件。

什么是模式?
在正則表達式的上下文中,模式是字符序列的文本表示法。例如,假如您想知道一個字符序列中是否存在 car 這個詞,您會使用模式 car,因為這是精確地表示該字符串的方法。對于更復雜的模式,您可以使用非凡字符作為占位符。假如您不是要搜索 car,而是想搜索以字母 c 開頭并以字母 r 結尾的任何文本字符串,您會使用 c*r 模式,其中 * 代表第一個 r 前的任意多個字符。c*r 模式將匹配任何以 c 開頭并以 r 結尾的字符串,如 cougar、cavalier 或 chrysler。

如何指定模式表達式
模式匹配的主要部分是關于要使用什么樣的表達式。Pattern 先保存要使用的表達式,然后將其傳遞給 Matcher 類以便在字符序列的上下文中檢查其匹配情況。例如,假如您想驗證一個電子郵件地址,您可能要檢查用戶輸入是否與這樣一個模式匹配 ? 它包含一個字母數字序列,后跟一個 @ 符號,@ 后又跟兩組用句點隔開的字符。這可以用表達式 p{Alnum}+@w+.p{Alpha}{2,3} 來表示。(是的,這過于簡化了電子郵件地址的結構,可能會排除某些有效的電子郵件地址,但它作為示例已經足夠了。)

在討論模式語言的具體細節之前,我們來仔細看一下 p{Alnum}+@w+.p{Alpha}{2,3}。p{Alnum} 序列表示單個字母數字字符(A 到 Z、a 到 z 或 0 到 9)。p{Alnum} 后面的加號(+)被稱為量詞(quantifier)。它被應用在表達式的前面部分,表示 p{Alnum} 必須出現一次或更多次。使用星號(*)表示要出現零次或一次以上(含一次)。@ 就是意味著它必須出現在至少一個字母數字字符之后,這樣整個模式匹配才能成功。w+ 與 p{Alnum}+ 類似,但添加了下劃線(_)。某些序列有多個表達式。反斜杠( .)代表句點。假如前面沒有反斜杠,單獨一個句點代表任意字符。最后的 p{Alpha}{2, 3} 表示兩個或三個字母字符。

只要學會了規范語言,您就能把握模式的所有秘密。我們來看一些更常用的表達式的種類:

文字(Literal):表達式內任何不具有非凡意義的字符都被看作是一個文字,并與自身匹配。


量詞(Quantifier):某些字符或表達式,它們被用來計算一個文字或分組可以在字符序列中出現的次數,以便該序列與表達式匹配。分組是由圓括號內的一組字符指定的。
? 表示出現一次或根本不出現
* 表示出現零次或一次以上(含一次)
+ 表示出現一次或多次


字符類(Character class):一個字符類就是方括號內的一個字符集,其中,匹配可以是括號內的任意一個字符。您可以把字符類與量詞結合在一起,例如,[acegikmoqsuwy]* 將是只包含字母表中奇數字母的任意字符序列。某些字符類是預先定義的:
d ? 數字(0 到 9)
D -- 非數字
s -- 空白字符,如制表符或換行符
S -- 非空白字符
w -- 單字字符(a 到 z、A 到 Z、0 到 9 以及下劃線)
W -- 非單字字符(其它任意字符)


Posix 字符類(Posix character class):某些字符類僅在用于 US-ASCII 比較時才有效。例如:
p{Lower} ? 小寫字符
p{Upper} ? 大寫字符
p{ASCII} ? 所有 ASCII 字符
p{Alpha} ? 字母字符(p{Lower} 與 p{Upper} 相結合)
p{Digit} ? 從 0 到 9 的數字
p{Alnum} ? 字母數字字符


范圍(Range):使用短線(dash)來指定包括一定范圍字符的字符類。例如,[A-J] 表示從 A 到 J 的大寫字母。


否定(Negation):脫字符(^)否定字符類的內容。例如,[^A-J] 表示除 A 到 J 之外的任何字符。
請參閱 Pattern API 文檔(可以從參考資料找到)了解關于序列的其它具體信息。

如何有效地使用模式
既然您已經了解了如何指定模式,我們就來使用它們吧。您需要讓 Pattern 類編譯它們,如下所示。注重,反斜杠字符()在 String 常量中需要轉義。


Pattern pattern = Pattern.compile(
"/p{Alnum}+@/w+/./p{Alpha}{2,3}");



有了一個編譯好的模式后,您可以使用 Pattern 類根據模式把一個輸入行分割為一系列單字,或者使用 Matcher 類執行一些更復雜的任務。下面說明了如何分割輸入字符序列,其中使用的模式指定了分隔符,而不是字:


String Words[] = pattern.split(input);



假如您想在一個字符序列中多次匹配一個模式,上面的代碼片段是一個很好的起點。但假如您想獲取特定的輸入,您將需要 Pattern 的 matcher() 方法。在給定某個輸入時,這個方法將返回適當的 Matcher 類。接著,您使用 Matcher 實例遍歷整個結果在輸入序列中查找不同的模式匹配,或者使用 Matcher 實例作為查找-替換工具(后一種方法更好):


Matcher matcher = pattern.matcher(input);



要根據整個序列匹配模式,請使用 matches()。要確定是否只有序列的一部分匹配,請使用 find():


if (matcher.find()) {
// Found some string within input sequence
// That matched the compiled pattern
String match = matcher.group();
// PRocess matching pattern
}



完整的示例
這兩個類(Pattern 與 Matcher)就是整個模式匹配庫。提出正確的正則表達式,然后使用 Matcher 類的結果,這就是這個模式匹配庫要做的全部工作。在針對 Java 語言的關于正則表達式的專門書籍出現之前,請找一本關于 Perl 的好書來進一步了解特定的模式。清單 1 提供了一個完整的示例,該示例將在特定文件中查找從命令行作為輸入而傳入的最長單詞。

清單 1.“最長的單詞”示例
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.util.*;
import java.util.regex.*;

public class Longest {
public static void main(String args[]) {
if (args.length != 1) {
System.err.println("Provide a filename");
return;
}

try {
// Map File from filename to byte buffer
FileInputStream input =
new FileInputStream(args[0]);
FileChannel channel = input.getChannel();
int fileLength = (int)channel.size();
MappedByteBuffer buffer = channel.map(
FileChannel.MapMode.READ_ONLY, 0, fileLength);

// Convert to character buffer
Charset charset = Charset.forName("ISO-8859-1");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(buffer);

// Create line pattern
Pattern linePattern =
Pattern.compile(".*$", Pattern.MULTILINE);

// Create word pattern
Pattern wordBreakPattern =
Pattern.compile("[/p{Punct}/s}]");

// Match line pattern to buffer
Matcher lineMatcher =
linePattern.matcher(charBuffer);

// Holder for longest word
String longest = "";

// For each line
while (lineMatcher.find()) {

// Get line
String line = lineMatcher.group();

// Get array of words on line
String words[] = wordBreakPattern.split(line);

// Look for longest word
for (int i=0, n=words.length; i<n; i++) {
if (words[i].length() > longest.length()) {
longest = words[i];
}
}
}
// Report
System.out.println("Longest word: " + longest);

// Close
input.close();
} catch (IOException e) {
System.err.println("Error processing");
}
}
}



參考資料

請單擊文章頂部或底部的討論參加關于本文的討論論壇。


請閱讀 java.util.regex 包的 API 文檔。


請試用面向 Java 版本 1.4 之前的 alphaWorks Regex for Java。


developerWorks linux 專區發表了一個 Cultured Perl 月刊專欄,這個專欄可能向您提供使用 Java 語言的正則表達式的比較深入的知識。


閱讀 John Zukowski 寫的 Merlin 技巧全集。


請在 developerWorks Java 技術專區上查找更多的 Java 參考資料。

關于作者
John Zukowski 通過 JZ Ventures, Inc. 從事戰略性 Java 咨詢,同時還擔任一些 jGuru 的由社區推動的 Java 常見問題解答的常駐指導。他最近的著作有 Apress 出版的 Learn Java with JBuilder 6 與 Sybex 出版的 Mastering Java 2: J2SE 1.4 。請通過 jaz@zukowski.net 與他聯系。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 涿鹿县| 江达县| 千阳县| 广平县| 贵阳市| 尼玛县| 麟游县| 阿克| 林周县| 邛崃市| 和平区| 京山县| 界首市| 鞍山市| 乌拉特中旗| 汾西县| 滨海县| 新民市| 河北区| 赤水市| 固阳县| 北京市| 灵川县| 新干县| 广南县| 大同市| 增城市| 体育| 玛纳斯县| 沁源县| 车险| 武胜县| 甘洛县| 武冈市| 旺苍县| 高密市| 浦江县| 合作市| 金溪县| 尼木县| 岳池县|