Java正则表达式学习(四)

10. Pattern 类的方法


10.1 使用标志构造模式


Pattern类定义了备用的compile方法,用于接受影响模式匹配方式的标志集。标志参数是一个位掩码,可以用下面的公共静态字段中任意一个:


Pattern.CANON_EQ


启动规范等价。在指定此标志后,当且仅当在其完整的规范分解匹配时,两个字符被视为匹配。例如,表达式

a\u030A 在指定此标识后,将匹配字符串"\u00E5" (即字符a)。默认情况下,匹配不会采用规范等价。指定此标志可能会对性能有一定的影响。


Pattern.CASE_INSENSITIVE


启动不区分大小写匹配。默认情况下,仅匹配US-ASCII字符集的字符。Unicode感知(Unicode-aware)的不区分大小写匹配,可以通过指定UNICODE_CASE标志连同此标志来启用。不区分大小写匹配也能通过内嵌标志表达式(?i)来启用。指定此标识可能会对性能有一定的影响。


Parttern.COMMNETS


模式中允许存在空白和注释。在这种模式下,空白和以#开始的直到行尾的内嵌注释会被忽略。注释模式也能通过内嵌标示表达式(?x)来启用。


Parttern.DOTALL


启用dotall模式。在dotall模式下,表达式. 匹配包括行结束符在内的任意字符。默认情况下,表达式不会匹配行结束符。dotall模式也通过内嵌表达式(?x)来启用。[s是"单行(single-line)"模式的助记符,与Perl中相同。]


Pattern.LITERAL


启用模式的字面分析。指定该标识后,指定模式的输入字符串作为字面上的字符序列来对待。输入序列中的元字符和转义字符不具有特殊的意义了 。CASE_INSENSITIVE 和 UNICODE_CASE 与此标识一起使用时,会对匹配产生一定的影响。其他的标识就变得多余了。启用字面分析没有内嵌标识的表达式。


Pattern.MULTILINE


启用多行(multiline)模式。在多行模式下,表达式^和$分别匹配输入序列行结束符前面和结束符的前面。默认情况下,表达式仅匹配整个输入序列的开始和结尾。多行模式也能通过内嵌标示表达式(?m)来启用。


Pattern.UNICODE_CASE


启用可折叠感知Unicode(Unicode-aware case folding) 大小写。在指定此标识后,需要通过CASE_INSENSITIVE标识来启用,不区分大小写区配将在Unicode标准的意义上来完成。默认情况下,不区分大小写匹配仅匹配US-ASCII字符集中的字符。可折叠感知Uncode大小写也能通过内嵌标识表达式(?u)来启用。指定此标识可能会对性能有一定影响。


Pattern.UNIX_LINES


启用Unix行模式。在这种模式下,. ^和$的行为仅识别"\n"的行结束符。Unix行模式可以通过内嵌标识表达式(?d)来启用。


接下来,将修改测试工具 RegexTestHarness.java ,用于构建不区分大小写匹配的模式。


首先,修改代码去调用complie 的另外一个备用的方法:



Pattern pattern = Pattern.compile(scanner.nextLine(),Pattern.CASE_INSENSITIVE);



编译并运行这个测试工具,会得到下面的结果:



Enter your regex: dog
Enter input string to search: DoGDOg
I found the text "DoG" starting at index 0 and ending at index 3.
I found the text "DOg" starting at index 3 and ending at index 6.

 


正如你所看到的,不管是否大小写,字符串字面上是"dog"的都产生了匹配。使用多个标识来编译一个模式,使用按位或操作符"|"分隔各个标志。为了更清晰地说明,下面的示例代码使用硬编码(hardcode)的方式,来取代控制台中的读取:



pattern = Pattern.compile("[az]$", Pattern.MULTILINE | Pattern.UNIX_LINES);



也可以使用一个int类型的变量来代替:



final int flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE; 
Pattern pattern = Pattern.compile("aa", flags);



10.2 内嵌标识的表达式


使用内嵌标识的表达式(embedded flag expressions)也可以启动不同的标志。对于两个参数的compile方法,内嵌标识表达式是可选的,因为它在自身的正则表达式中被指定了。下面的例子使用最初的测试工具(RegexTestHarness.java),使用内嵌标识表达式(?i)来启用不区分大小写的匹配。


Enter your regex: (?i)foo
Enter input string to search: FOOfooFoOfoO
I found the text "FOO" starting at index 0 and ending at index 3.
I found the text "foo" starting at index 3 and ending at index 6.
I found the text "FoO" starting at index 6 and ending at index 9.
I found the text "foO" starting at index 9 and ending at index 12.


所以匹配无关大小写都一次次地成功了。


内嵌标识表达式所对应Pattern的公有的访问字段表示如下表:


常  量等价的内嵌标志表达式
Pattern.CANON_EQ没有
Pattern.CASE_INSENSITIVE(?i)
Pattern.COMMENTS(?x)
Pattern.MULTILINE(?m)
Pattern.DOTALL(?s)
Pattern.LITERAL没有
Pattern.UNICODE_CASE(?u)
Pattern.UNIX_LINES(?d)


10.3 使用matches(String,CharSequence)方法


Pattern类定义了一个方便的matches方法,用于快速地检查模式是否标识给定的输入字符串。与使用所有的公共静态方法一样,应该通过它的类名来调用matches方法,诸如Pattern.matches("\\d","1"); 。在这个例子中,方法返回true,这是由于数字"1"匹配了正则表达式\d.


10.4 使用split(String)方法


split 方法是一个重要的工具,用于收集依赖于被匹配的模式任一边的文本。如下面的SplitDemo.java所示,split方法能从"one:two:three:four:five" 字符串中解析出"one two three four five"单词:



package com.fortune.test;

import java.util.regex.Pattern;

/**
 * Created with IntelliJ IDEA.
 * User: Alan
 * Date: 12-5-29
 * Time: 下午4:41
 */
public class SplitDemo {
    private static final String REGEX = ":";
    private static final String INPUT = "one:two:three:four:five";

    public static void main(String[] args) {
        Pattern p = Pattern.compile(REGEX);
        String[] items = p.split(INPUT);
        for (String s : items) {
            System.out.println(s);
        }

    }
}

 

输出:



one
two
three
four
five

 


简而言之,已经使用冒号(:)取代了复杂的正则表达式匹配字符串文字。以后仍然使用Pattern和Matcher对象,也能使用split得到位于任意正则表达式各边的文本。下面的SplitDemo2.java是个一样的例子,使用数字作为split的参数:



package com.fortune.test;

import java.util.regex.Pattern;

/**
 * Created with IntelliJ IDEA.
 * User: Alan
 * Date: 12-5-29
 * Time: 下午4:41
 */
public class SplitDemo2 {
    private static final String REGEX = "\\d";
    private static final String INPUT = "one9two4three7four1five";

    public static void main(String[] args) {
        Pattern p = Pattern.compile(REGEX);
        String[] items = p.split(INPUT);
        for (String s : items) {
            System.out.println(s);
        }

    }
}

 


输出:



one
two
three
four
five

 


10.5 其它有用的方法


你可以从下面的方法中找到比较好用的方法:


public static String quote(String s) : 返回指定字符串字面模式的字符串。此方法会产生一个字符串,能被用于构建一个与字符串s匹配的Pattern,好像它是字面上的模式。输入序列中的元字符和转义序列将没有特殊的意义了。


public String toString() : 返回这个模式的字符串表现形式。这是一个编译过的模式中的正则表达式。



10.6 在java.lang.String 中等价的Pattern方法


java.lang.String 通过模拟 java.util.regex.Pattern行为的几个方法,也可以支持正则表达式。方便起见,下面主要摘录了出现在API关键的方法。


public boolean matches(String regex) : 告知字符串是否匹配给定的正则表达式。调用str.matches(regex) 方法所产生的结果与作为表达式的Pattern.matches(regex,str)的结果是完全一致。


public String[] split(String regex,int limit) : 依照匹配给定的正则表达式来拆分字符串。调用str.split(regex,n) 方法所产生的结果与作为表达式的Pattern.compile(regex).split(str,n)的结果完全一致。


public String[] split(String regex) :依照匹配给定的正则表达式来拆分字符串,这个方法与调用两个参数的split方法是相同的,第一个参数使用给定的表达式,第二个参数限制为0。在结果数组中不包括尾部的空字符串。


还有一个替代方法,把一个CharSequence替换成另外一个:


public String replace(CharSequence target,Charsequence replacement) :将字符串中每一个匹配替换匹配字符目标序列的子字符串,替换成指定的字面替换序列。这个替换从字符串的开始处理直至结束,例如,把字符串"aaa"中的"aa"替换成"b",结果是"ba",而不是"ab".


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值