正则入门

Posted xanlv

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正则入门相关的知识,希望对你有一定的参考价值。

首先,大概浏览一下正则的api字典:Pattern类 Matcher类

正则表达式(regular expression,简写为regex、regexp或RE),又称规则表达式。计算机科学的一个概念,描述了一种字符串匹配的模式(pattern),用来检索、替换那些符合某个模式(规则)的文本。查找的某个字符或者子字串、或者对字符串进行分割、或者对字符串一些字符进行替换/删除

正则表达式是匹配模式,要么匹配字符,要么匹配位置。

1.正则基础
正则两种模糊匹配:

      横向模糊匹配:一个正则可匹配的字符串的长度不是固定的,可以是多种情况的。其实现的方式使用量词。如:ab2,5c

      纵向模糊匹配:一个正则匹配的字符串,具体到某一位字符时,它可以不是某个确定的字符,可以有多种可能。其实现的方式是使用字符组。如:a[123]b

正则字符组:虽叫字符组(字符类),但只是其中一个字符。例如[abc],表示匹配一个字符,它可以是“a”、“b”、“c”之一。

       范围表示法:比如[1-9a-zG-Z]。用连字符"-"来省略和简写。注:连字符有特殊用途,匹配"-"时,要么放在开头,要么放在结尾,要么转义。

       排除字符组:字符组的第一位放"^"(脱字符),表示求反的概念。如[^a-c]:排除a,b,c

       理解一些元字符.:通配符,表示几乎任意字符。换行符、回车符、行分隔符和段分隔符除外。记忆方式:想想省略号...中的每个点,都可以理解成占位符,表示任何类似的东西。

                                \\w和\\W:是与非的关系,\\w匹配数字字母,\\W则是非数字字母.注:很多类似的\\d和\\D都是这种关系

正则量词:也称重复。

      简写形式:m,:至少出现m次。m:等价于m,m,表示出现m次。* 等价于0,,+ 等价于1,,? 等价于0,1

      贪婪匹配和惰性匹配:量词默认是贪婪的.惰性匹配,量词后面加个问号,问一问你知足了吗?

正则多选分支:支持多个子模式任选其一。 如:(p1|p2|p3),其中p1、p2和p3是子模式,用“|”(管道符)分隔,表示其中任何之一。

        注:分支结构也是惰性的,即当前面的匹配上了,后面的就不再尝试了,如:"abcd"用/abc|adbc/去匹配,得到abc,用/abcd|abc/去匹配,得到abcd

字面量,匹配一个具体字符,包括不用转义的和需要转义的。比如a匹配字符”a”,又比如\\n匹配换行符,又比如.匹配小数点。

锚点,匹配一个位置,而不是字符。比如^匹配字符串的开头,又比如\\b匹配单词边界,又比如(?=\\d)表示数字前面的位置。

分组,用括号表示一个整体,比如(ab)+,表示”ab”两个字符连续出现多次,也可以使用非捕获分组(?:ab)+。

反向引用,比如\\2,表示引用第2个分组。

正则操作符: 转义符 \\

               括号和方括号 (...)、(?:...)、(?=...)、(?!...)、[...] 

                量词限定符 m、m,n、m,、?、*、+ 

                位置和序列 ^ 、$、 \\元字符、 一般字符     

                管道符(竖杠) |

              优先级从上至下,由高到低

所有结构里,用到的元字符总结如下:^ $ . * + ? | \\ \\/ [ ] = ! : - ,

总结:匹配字符,无非就是字符组、量词和分支结构的组合使用。

2.java使用正则
pattern 对象是一个正则表达式的编译表示。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。

Matcher 对象是对输入字符串进行解释和匹配操作的引擎。需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。

PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。

//       1.
        System.out.println("".matches(""));


//      2.
        String s = "2.21";
//        String regEx = "^\\\\d+(\\\\.\\\\d+)?";
        String regEx = "^[0-9]+(\\\\.[0-9]+)?";//() 域段
        Pattern pat = Pattern.compile(regEx);
        Matcher mat = pat.matcher(s);
        boolean rs = mat.find();
        System.out.println(rs);

//      3.
        String content = "I am noob from runoob.com.";
        String pattern = ".*runoob.*";
        //.点:匹配除“\\n”之外的任何单个字符。要匹配包括“\\n”在内的任何字符,请使用像“[\\s\\S]”的模式。
        boolean isMatch = Pattern.matches(pattern, content);
        System.out.println("字符串中是否包含了 'runoob' 子字符串? " + isMatch);
        Pattern pattern = Pattern.compile("[, |]+");
        String[] strs = pattern.split("Java Hello World  Java,Hello,,World|Sun");
        for (int i = 0; i < strs.length; System.out.println(strs[i]), i++) ;
        String[] strs2 = pattern.split("Java Hello World  Java,Hello,,World|Sun", 3);
        //limt在1,strs.length,不在这个范围,则都默认拆分最大数量
        for (int i = 0; i < strs2.length; System.out.println(strs2[i]), i++) ;

        //文字替换
        Pattern p = Pattern.compile("正则表达式");
        Matcher matcher = p.matcher("正则表达式 Hello World,正则表达式 Hello World");
        //替换第一个符合正则的数据
//        System.out.println(matcher.replaceFirst("Java"));
//        System.out.println(matcher.replaceAll("java"));
        StringBuffer sbr = new StringBuffer();
        while (matcher.find()) 
            matcher.appendReplacement(sbr, "Java");//(置换字符)
            System.out.println(sbr.toString());
        
        matcher.appendTail(sbr);//最后一次匹配工作后剩余的字符串添加到一个StringBuffer对象里。
        System.out.println(sbr.toString());

javascript使用,支持三个模式

<script>
//var str = "02abc";
var str = "02Abc";
//var patt1 = /^\\d+abc$/;
var patt1 = /^[0-9]+abc$/ig;
document.write(str.match(patt1)+"<br/>");


var str2 = "Is is the cost of of gasoline going up up 2 3 2";
//var patt2 = /\\b([a-z]+) \\1\\b/ig;
var patt2 = /\\b(\\w+) \\1\\b/ig;
document.write(str2.match(patt2));

//i模式--表示匹配是非大小写敏感的
//g模式--表示匹配是全局的,即在目标字符串中按顺序找到满足匹配模式的所有子串,强调的是“所有”,而不只是“第一个”
//m模式--表示多行查找匹配模式,该模式下,^  $除了匹配整个查找字符串的首位外,还匹配每一行的首位位置。

var str3 = "abcs SDsdD f12";
var reg = new RegExp("[a-z]+","gi");
document.write(str3.match(reg));
</script>

3.java Pattern的八种模式

DOTALL: 表达式’.’可以匹配任意字符(包括行的结束符)。默认情况下,表达式’.’不匹配行的结束符。/r/n Windows。/n Unix/Linux。/r Mac。

UNIX_LINES: 只有’行的结束符’才被认作一行的中止,并且与’.’,’^’,以及’$’进行匹配

COMMENTS: 忽略空白(不是指表达式里的”\\s”,而是指表达式里的空格,tab,回车之类)和在结束行之前以 # 开头的嵌入式注释。

MULTILINE: 多行模式。’^’和’$’分别匹配一行和字符串的开始和结束。默认情况下,这两个表达式仅仅匹配字符串的开始和结束。

LITERAL: 纯文本模式。指定模式的输入字符串被视为文字字符序列。在输入序列中,元字符或转义序列没有特殊意义。CASE_INSENSITIVE和UNICODE_CASE保留它们对匹配的影响。其他的模式变得多余了。

UNICODE_CASE: 规范等价,不同的编码中相同的字符视为相等。如果Unicode的编码和字符的Ascoll码值是一样的,则进行匹配,如A和\\u0041

CASE_INSENSITIVE: 对ASCII字符进行不区分大小写匹配。默认情况下,大小写不明感的匹配只适用于US-ASCII字符集。

UNICODE_CHARACTER_CLASS: 只有jdk1.7+才支持,启用了预定义字符类的Unicode版本

String str = "aaa\\r\\nbbb";
String pattern = ".+";
System.out.println("DOTALL-'.'可以匹配任意字符(包括行的结束符)");
print(str, pattern, 0, "not DOTALL");
print(str, pattern, Pattern.DOTALL, "DOTALL");

System.out.println("UNIX_LINES-只有'行的结束符'才被认作一行的中止,并且与'.','^',以及'$'进行匹配");
print(str, pattern, Pattern.UNIX_LINES, "UNIX_LINES");
System.out.println("test\\r123");//将输入光标重置于行的开始处
str = "aaa\\rbbb";
print(str, pattern, Pattern.UNIX_LINES, "UNIX_LINES IN WINDOWS");
str = "aaa\\r\\nbbb";
print(str, pattern, Pattern.UNIX_LINES, "UNIX_LINES IN WINDOWS");

System.out.println("COMMENTS-忽略空白和在以#开头的注释。");
str = "aacba\\r\\naab ab\\r\\nbbb";
pattern = "aa.+ b#comment";
print(str, pattern, Pattern.COMMENTS, "COMMENT");// whitespace is ignored.

pattern = ".+b$";
System.out.println("MULTILINE-多行模式^、$分别表示匹配行首和行尾");
print(str, pattern, 0, "not NULTILINE");
print(str, pattern, Pattern.MULTILINE, "NULTILINE");

System.out.println("LITERAL-输入字符串被视为文字字符");
pattern = "bb";
str = "aacbba\\r\\naab ab\\r\\nbbb .bb .+bb";
print(str, pattern, Pattern.LITERAL, "LITERAL");
pattern = ".+bb";
print(str, pattern, Pattern.LITERAL, "LITERAL");

System.out.println("CANON_EQ-不同的编码中相同的字符视为相等.");
print("AA", "\\u0041", Pattern.CANON_EQ, "CANON_EQ");

System.out.println("UNICODE_CASE-对Unicode字符区分大小写匹配");
print("aa", "\\u0041", Pattern.UNICODE_CASE, "UNICODE_CASE");
print("aa", "\\u0041", Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE, "UNICODE_CASE|CASE_INSENSITIVE");

System.out.println("UNICODE_CHARACTER_CLASS-启用预定义字符类和POSIX字符类的Unicode版本");
print("aaAB", "\\\\pLower", Pattern.UNICODE_CHARACTER_CLASS, "UNICODE_CHARACTER_CLASS");
print("aaAB", "\\\\pUpper", Pattern.UNICODE_CHARACTER_CLASS, "UNICODE_CHARACTER_CLASS");
print("aaAB啦啦啦", "\\\\w+", 0, "UNICODE_CHARACTER_CLASS");
print("aaAB啦啦啦", "\\\\w+", Pattern.UNICODE_CHARACTER_CLASS, "UNICODE_CHARACTER_CLASS");

4.正则表达式实战
1)POSIX字符类型:上面Pattern类中有,也有Unicode 块和类别的类,使用方法同

       //匹配出一个文本里面的所有(英文半角)标点符号
        String pattern = "[-!\\"\\\\#\\\\$%&'()*+,./:;\\\\\\\\<=>?@\\\\[\\\\]\\\\^_`\\\\\\\\|\\\\~]";
        String str = "1~2-6,C#,1+2=3;@qq.com2^3functon()/\\\\";
        System.out.println("-------------文本里面的所有(英文半角)标点符号-----------------------------");
        print(str, pattern, 0);
//        print(str, "\\\\\\\\", 0);
        System.out.println("-------------文本里面的所有(英文半角)标点符号-POSIX字符类来实现------------");
        print(str, "\\\\pPunct", 0);
        print("aa环保部", "\\\\pL+", 0);

2)电话的正则

5.正则优化
正则表达式匹配字符串的这种方式,有个学名,叫回溯法。

回溯法也称试探法,它的基本思想是:从问题的某一种状态(初始状态)出发,搜索从这种状态出发所能达到的所有“状态”,当一条路走到“尽头”的时候(不能再前进),再后退一步或若干步(即 回溯),从另一种可能“状态”出发,继续搜索,直到所有的“路径”(状态)都试探过。这种不断“前进”、不断“回溯”寻找解的方法,就称作“回溯法”。(见百度)

以上是关于正则入门的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式

正则表达式入门

正则表达式规则

java正则表达式-量词

java正则表达式-量词

正则表达式量词