正则表达式

正则表达式是一种强大而灵活的文本处理工具。使用正则表达式,我们能够以编程的方式,构造复杂的文本模式,并对输入的字符串进行搜索。

1 基础

一般来说,正则表达式就是以某种方式来描述字符串。
在正则表达式中,用\d表示一位数字。由于Java对反斜线的不同处理,在其它语言中,\表示想要在正则表达式中插入一个普通的反斜线,请不要给他任何特殊的意义。而在Java中,\的意思是我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。例如,如果想表示一位数字,那么正则表达式应该是\d。如果你想插入一个普通的反斜线,则应该这样\\。不过换行和制表符之类的东西只需使用单反斜线:\n\t。

构建正则表达式

字符说明
\将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如,”n”匹配字符”n”。”\n”匹配换行符。序列”\\”匹配”\”,”\(“匹配”(“。
零次或一次匹配前面的字符和子表达式
+一次或多次匹配前面的字符和子表达式
*零次或多次匹配前面的字符和子表达式
.匹配除”\r\n”之外的任何单个字符
B指定字符B
\xhh十六进制为oxhh的字符
\uhhhh十六进制表示为oxhhhh的Unicode字符
\t制表符Tab
\n换行符
\r回车
\f换页
\e转义(Escape)

例如,表示”可能有一个负号,后面跟着一位或多位数字“,可以这样:-?\d+

public class IntegerMatch{
    public static void main(String[] args){

        System.out.println("-1234".matches("-?\\d+"));
        System.out.println("4568".matches("-?\\d+"));
        System.out.println("+4568".matches("-?\\d+"));
        //字符+在正则表达式中有特殊意义,所以必须使用\\转义
        //在正则表达式中,括号有着将表达式分组的效果,竖直线|则表示或操作。
        System.out.println("+4568".matches("(-|\\+)?\\d+"));    
    }
}
/*
运行结果为(做的是一个完全匹配):
true
true
false
true
*/
字符类
任意字符
[abc]包含a、b和c的任何字符(和a
[^abc]除了a、b和c的任何字符(否定)
[a-zA-Z]从a到z或从A到Z的任何字符(范围)
[abc[hij]]任意a、b、c、h、i和j字符(合并)
[a-z&&[hij]任意h、i和j(相交)
\s空白符(空格、tab、换行、换页、回车)
\S非空白符([^\s])
\d数字[0-9]
\D非数字[^0-9]
\w词字符[a-zA-Z0-9]
\W非词字符[^\w]
逻辑操作符
XYY跟在X后面
XY
(X)捕获组。可以在表达式中用\i引用第i个捕获组
边界匹配符
^一行的起始
$一行的结束
\b词的边界
\B非词的边界
\G前一个匹配的结束

量词
量词描述了一个模式吸收输入文本的方式:
1. 贪婪型:贪婪表达式会为所有可能的模式发现尽可能多的匹配。假定我们的模式仅能匹配第一个可能的字符组,如果它是贪婪的,那么它就会继续往下匹配。
2. 勉强型:用问号来指定,这个量词匹配满足模式所需的最少字符数。
3. 占有型:这种类型的量词只在Java语言中才可用。用于防止正则表达式失控,因此可以是正则表达式执行起来更有效。

贪婪型勉强型占有型如何匹配
X?X??X?+一个或零个X
X*X*?X*+零个或多个X
X+X+?X++一个或多个X
X{n}X{n}?X{n}+恰好n次X
X{n,}X{n,}?X{n,}+至少n次X
X{n,m}X{n,m}?X{n,m}+X至少n次,且不超过m次

表达式X通常必须要用括号括起来。例如:
abc+ 匹配ab,后面跟随一个或多个c
(abc)+ 匹配一个或多个完整的abc字符串

下面是一个测试正则表达式的程序:

import java.util.regex.*;
public class TestRegex{
    public static void main(String[] args){
        if(args.length < 2){
            pf("需要待测试的字符串 正则表达式");
            System.exit(0);
        }

        pf("Input: \""+args[0]+"\"");
        for(String arg : args){
            pf("Regex: \""+arg+"\"");
            Pattern p = Pattern.compile(arg);
            Matcher m = p.matcher(args[0]);
            //find()像迭代器那样前向遍历输入字符串
            while(m.find()){
                pf("Match \""+m.group()+"\" at positions "+
                    m.start()+" - "+(m.end()-1));
            }
        }
    }
    static void pf(String s){
        System.out.println(s);
    }
}
/*
Input: "ababababasba"
Regex: "ababababasba"
Match "ababababasba" at positions 0 - 11
Regex: "ab"
Match "ab" at positions 0 - 1
Match "ab" at positions 2 - 3
Match "ab" at positions 4 - 5
Match "ab" at positions 6 - 7
注意:通过参数传入的正则表达式含有\,
如\d,只需要写一个\即可,这和在程序中写\\d不同。
*/


组是用括号划分的正则表达式,可以根据组的编号来引用某个组。组号为0表示整个表达式,组号1表示被第一对括号括起的组,依次类推。
A(B(C))D
有三个组:组0是ABCD,组1是BC,组2是C。

import java.util.regex.*;
public class Groups{
    public static final String POEM =
    "Twas briling, and the slithy toves\n"+
    "Did gyre and gimble in the wabe.\n"+
    "All mimsy were the borogoves,\n"+
    "And the mome raths outgrabe.\n\n"
    ;

    public static void main(String[] args){
        Matcher m = 
         Pattern.compile("(\\S+)\\s+((\\S+)\\s+)$").matcher(POEM);
         System.out.println("整个匹配(组0)情况为:");
         while(m.find()){
             System.out.print("{"+m.group()+"}");
         }
         System.out.println();
         m.reset(); //重置标记
         while(m.find()){
             System.out.println(m.groupCount());
             for(int j=0;j<=m.groupCount();j++){
                 System.out.print("{ j="+j+"  "+m.group(j)+"}");
             }
             System.out.println();
         }

    }
}
/*
运行结果为:
整个匹配(组0)情况为:
{raths outgrabe.

}
3
{ j=0  raths outgrabe.

}{ j=1  raths}{ j=2  outgrabe.

}{ j=3  outgrabe.}
分析:组是以括号表示的,
 m.groupCount()返回该匹配器的模式中的分组数目,不包括组0(整个匹配)
首先第一次匹配全部,然后在其中依次匹配(\\S+)、((\\S+)\\s+)、(\\S+)
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值