JAVA 正则表达式教程(超详细)二(续)

2019-03-16 18:57|来源: 陈广佳

       第二点是,在本地号码位的前三位和后四位数字间有可能是空格符,而不是连字号,更有胜者,或根本就没有分隔符,就是7位数字连在一起。对这几种情况,我们可以用(-|)?来解决。这个结构的正则表达式就是转换器,它能匹配上面所说的几种情况。在()能含有管道符|时,它能匹配是否含有空格符或连字符,而尾部的?元字符表示是否根本没有分隔符的情况。


  最后,区位号也可能没有包含在圆括号内,对此可以简单地在圆括号后附上?元字符,但这不是一个很好的解决方法。因为它也包含了不配对的圆括号,比如"(555" 或 "555)"。相反,我们可以通过另一种转换器来强迫让电话号码是否带有有圆括号:(/(/d{3}/)|/d{3})。如果我们把上面代码中的正则表达式用这些改进后的来替换的话,上面的代码就成了一个非常有用的电话号码数字匹配器:

  Pattern pattern = Pattern.compile("(//(//d{3}//)|//d{3})//s?//d{3}(-|)?//d{4}");


  可以确定的是,你可以自己试着进一步改进上面的代码。

  现在看看第二个例子,它是从Friedl的中改编过来的。其功能是用来检查文本文件中是否有重复的单词,这在印刷排版中会经常遇到,同样也是个语法检查器的问题。

  匹配单词,像其他的一样,也可以通过好几种的正则表达式来完成。可能最直接的是/b/w+/b,其优点在于只需用少量的regex元字符。其中/w元字符用来匹配从字母a到u的任何字符。+元字符表示匹配匹配一次或多次字符,/b元字符是用来说明匹配单词的边界,它可以是空格或任何一种不同的标点符号(包括逗号,句号等)。

  现在,我们怎样来检查一个给定的单词是否被重复了三次?为完成这个任务,需充分利用正则表达式中的所熟知的向后扫描。如前面提到的,圆括号在正则表达式中有几种不同的用法,一个就是能提供组合类型,组合类型用来保存所匹配的结果或部分匹配的结果(以便后面能用到),即使遇到有相同的模式。在同样的正则表达中,可能(也通常期望)不止有一个组合类型。在第n个组合类型中匹配结果可以通过向后扫描来获取到。向后扫描使得搜索重复的单词非常简单:/b(/w+)/s+/1/b。

  圆括号形成了一个组合类型,在这个正则表示中它是第一组合类型(也是仅有的一个)。向后扫描/1,指的是任何被/w+所匹配的单词。我们的正则表达式因此能匹配这样的单词,它有一个或多个空格符,后面还跟有一个与此相同的单词。注意的是,尾部的定位类型(/b)必不可少,它可以防止发生错误。如果我们想匹配"Paris in the the spring",而不是匹配"Java's regex package is the theme of this article"。根据java现在的格式,则上面的正则表达式就是:Pattern pattern =Pattern.compile("//b(//w+)//s+//1//b");


  最后进一步的修改是让我们的匹配器对大小写敏感。比如,下面的情况:"The the theme of this article is the Java's regex package.",这一点在regex中能非常简单地实现,即通过使用在Pattern类中预定义的静态标志CASE_INSENSITIVE :

  Pattern pattern =Pattern.compile("//b(//w+)//s+//1//b",

  Pattern.CASE_INSENSITIVE);

  有关正则表达式的话题是非常丰富,而且复杂的,用Java来实现也非常广泛,则需要对regex包进行的彻底研究,我们在这里所讲的只是冰山一角。即使你对正则表达式比较陌生,使用regex包后会很快发现它强大功能和可伸缩性。如果你是个来自Perl或其他语言王国的老练的正则表达式的黑客,使用过regex包后,你将会安心地投入到java的世界,而放弃其他的工具,并把java的regex包看成是手边必备的利器。


CharSequence

JDK 1.4定义了一个新的接口,叫CharSequence。它提供了StringStringBuffer这两个类的字符序列的抽象:

interface CharSequence {
charAt(int i);
length();
subSequence(int start, int end);
toString();
}

为了实现这个新的CharSequence接口,StringStringBuffer以及CharBuffer都作了修改。很多正则表达式的操作都要拿CharSequence作参数。

PatternMatcher

先给一个例子。下面这段程序可以测试正则表达式是否匹配字符串。第一个参数是要匹配的字符串,后面是正则表达式。正则表达式可以有多个。在Unix/Linux环境下,命令行下的正则表达式还必须用引号。

//: c12:TestRegularExpression.java
// Allows you to easly try out regular expressions.
// {Args: abcabcabcdefabc "abc+" "(abc)+" "(abc){2,}" }
import java.util.regex.*;
publicclass TestRegularExpression {
    publicstaticvoid main(String[] args) {
    if(args.length < 2) {
        System.out.println("Usage:/n" + "java TestRegularExpression " +
                         "characterSequence regularExpression+");
        System.exit(0);
    }
    System.out.println("Input: /"" + args[0] + "/"");
    for(int i = 1; i < args.length; i++) {
        System.out.println("Regular expression: /"" + args[i] + "/"");
        Pattern p = Pattern.compile(args[i]);
        Matcher m = p.matcher(args[0]);
        while(m.find()) {
            System.out.println("Match /"" + m.group() +"/" atpositions " +
                                m.start() + "-" + (m.end() - 1));
      }
    }
  }
} ///:~

Java的正则表达式是由java.util.regexPatternMatcher类实现的Pattern对象表示经编译的正则表达式。静态的compile( )方法负责将表示正则表达式的字符串编译成Pattern对象。正如上述例程所示的,只要给Patternmatcher( )方法送一个字符串就能获取一个Matcher对象。此外,Pattern还有一个能快速判断能否在input里面找到regex

staticboolean matches(?regex, ?input)

以及能返回String数组的split( )方法,它能用regex把字符串分割开来。

只要给Pattern.matcher( )方法传一个字符串就能获得Matcher对象了。接下来就能用Matcher的方法来查询匹配的结果了。

boolean matches()
boolean lookingAt()
boolean find()
boolean find(int start)

matches( )的前提是Pattern匹配整个字符串,而lookingAt( )的意思是Pattern匹配字符串的开头。

find( )

Matcher.find( )的功能是发现CharSequence里的,与pattern相匹配的多个字符序列。例如:

//: c12:FindDemo.java
import java.util.regex.*;
import com.bruceeckel.simpletest.*;
import java.util.*;
publicclass FindDemo {
privatestatic Test monitor = new Test();
    publicstaticvoid main(String[] args) {
          Matcher m = Pattern.compile("//w+")
                           .matcher("Evening is full of the linnet's wings");
        while(m.find())
            System.out.println(m.group());
        int i = 0;
        while(m.find(i)) {
            System.out.print(m.group() + " ");
            i++;
        }
        monitor.expect(new String[] {
            "Evening",
            "is",
            "full",
            "of",
            "the",
            "linnet",
            "s",
            "wings",
            "Evening vening ening ning ing ng g is is s full " +
            "full ull ll l of of f the the he e linnet linnet " +
            "innet nnet net et t s s wings wings ings ngs gs s "
        });
    }
} ///:~

"//w+"的意思是"一个或多个单词字符",因此它会将字符串直接分解成单词。find( )像一个迭代器,从头到尾扫描一遍字符串。第二个find( )是带int参数的,正如你所看到的,它会告诉方法从哪里开始找——即从参数位置开始查找。

Groups

Group是指里用括号括起来的,能被后面的表达式调用的正则表达式。Group 0 表示整个表达式,group 1表示第一个被括起来的group,以此类推。所以;

A(B(C))D

里面有三个group:group 0是ABCD, group 1是BC,group 2是C

你可以用下述Matcher方法来使用group:

public int groupCount( )返回matcher对象中的group的数目。不包括group0。

public String group( ) 返回上次匹配操作(比方说find( ))的group 0(整个匹配)

public String group(int i)返回上次匹配操作的某个group。如果匹配成功,但是没能找到group,则返回null。

public int start(int group)返回上次匹配所找到的,group的开始位置。

public int end(int group)返回上次匹配所找到的,group的结束位置,最后一个字符的下标加一。

//: c12:Groups.java
import java.util.regex.*;
import com.bruceeckel.simpletest.*;
publicclass Groups {
    privatestatic Test monitor = new Test();
    staticpublicfinal String poem = "Twas brillig, 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" +
                    "Beware the Jabberwock, my son,/n" +
                    "The jaws that bite, the claws that catch./n" +
                    "Beware the Jubjub bird, and shun/n" +
                    "The frumious Bandersnatch.";
    publicstaticvoid main(String[] args) {
        Matcher m = Pattern.compile("(?m)(//S+)//s+((//S+)//s+(//S+))___FCKpd___6quot;).matcher(poem);
        while(m.find()) {
            for(int j = 0; j <= m.groupCount(); j++)
                System.out.print("[" + m.group(j) + "]");
                System.out.println();
            }
             monitor.expect(new String[]{
                "[the slithy toves]" +
                "[the][slithy toves][slithy][toves]",
                "[in the wabe.][in][the wabe.][the][wabe.]",
                "[were the borogoves,]" +
                "[were][the borogoves,][the][borogoves,]",
                "[mome raths outgrabe.]" +
                "[mome][raths outgrabe.][raths][outgrabe.]",
                "[Jabberwock, my son,]" +
                "[Jabberwock,][my son,][my][son,]",
                "[claws that catch.]" +
                "[claws][that catch.][that][catch.]",
                "[bird, and shun][bird,][and shun][and][shun]",
                "[The frumious Bandersnatch.][The]" +
                "[frumious Bandersnatch.][frumious][Bandersnatch.]"
        });
    }
} ///:~

这首诗是Through the Looking Glass的,Lewis Carroll的"Jabberwocky"的第一部分。可以看到这个正则表达式里有很多用括号括起来的group,它是由任意多个连续的非空字符('/S+')和任意多个连续的空格字符('/s+')所组成的,其最终目的是要捕获每行的最后三个单词;'$'表示一行的结尾。但是'$'通常表示整个字符串的结尾,所以这里要明确地告诉正则表达式注意换行符。这一点是由'(?m)'标志完成的(模式标志会过一会讲解)。

start( )和end( )

如果匹配成功,start( )会返回此次匹配的开始位置,end( )会返回此次匹配的结束位置,即最后一个字符的下标加一。如果之前的匹配不成功(或者没匹配),那么无论是调用start( )还是end( ),都会引发一个IllegalStateException。下面这段程序还演示了matches( )lookingAt( )

//: c12:StartEnd.java
import java.util.regex.*;
import com.bruceeckel.simpletest.*;
publicclass StartEnd {
privatestatic Test monitor = new Test();
    publicstaticvoid main(String[] args) {
        String[] input = new String[] {
            "Java has regular expressions in 1.4",
            "regular expressions now expressing in Java",
            "Java represses oracular expressions"};
        Pattern p1 = Pattern.compile("re//w*"),p2 = Pattern.compile("Java.*");
        for(int i = 0; i < input.length; i++) {
            System.out.println("input " + i + ": " + input[i]);
            Matcher m1 = p1.matcher(input[i]),m2 = p2.matcher(input[i]);
            while(m1.find())
                  System.out.println("m1.find() '" + m1.group() + 
                           "' start = "+ m1.start() + " end = " + m1.end());
            while(m2.find())
                  System.out.println("m2.find() '" + m2.group() + "' start = "+ 
                                    m2.start() + " end = " + m2.end());
            if(m1.lookingAt()) // No reset() necessary
                  System.out.println("m1.lookingAt() start = " + m1.start() + 
                                     " end = " + m1.end());
            if(m2.lookingAt())
                  System.out.println("m2.lookingAt() start = " + m2.start() + 
                                     " end = " + m2.end());
            if(m1.matches()) // No reset() necessary
                  System.out.println("m1.matches() start = " + m1.start() + 
                                     " end = " + m1.end());
            if(m2.matches())
                  System.out.println("m2.matches() start = " + m2.start() + 
                                     " end = " + m2.end());
        }
        monitor.expect(new String[] {
            "input 0: Java has regular expressions in 1.4",
            "m1.find() 'regular' start = 9 end = 16",
            "m1.find() 'ressions' start = 20 end = 28",
            "m2.find() 'Java has regular expressions in 1.4'" +
            " start = 0 end = 35",
            "m2.lookingAt() start = 0 end = 35",
            "m2.matches() start = 0 end = 35",
            "input 1: regular expressions now " +
            "expressing in Java",
            "m1.find() 'regular' start = 0 end = 7",
            "m1.find() 'ressions' start = 11 end = 19",
            "m1.find() 'ressing' start = 27 end = 34",
            "m2.find() 'Java' start = 38 end = 42",
            "m1.lookingAt() start = 0 end = 7",
            "input 2: Java represses oracular expressions",
            "m1.find() 'represses' start = 5 end = 14",
            "m1.find() 'ressions' start = 27 end = 35",
            "m2.find() 'Java represses oracular expressions' " +
            "start = 0 end = 35",
            "m2.lookingAt() start = 0 end = 35",
            "m2.matches() start = 0 end = 35"
        });
    }
} ///:~

注意,只要字符串里有这个模式,find( )就能把它给找出来,但是lookingAt( )matches( ),只有在字符串与正则表达式一开始就相匹配的情况下才能返回truematches( )成功的前提是正则表达式与字符串完全匹配,而lookingAt( )成功的前提是,字符串的开始部分与正则表达式相匹配。

JAVA 正则表达式教程(超详细)三(续)

相关问答

更多
  • 正则表达式的主要用法就是判断某个字符串是否符合某个固定的格式,以下是电话号码的格式判断: BufferedReader in;   Pattern pattern = Pattern.compile("//(//d{3}//)//s//d{3}-//d{4}");   in = new BufferedReader(new FileReader("18046521658"));   String s;   while ((s = in.readLine()) != null)   {   Matcher m ...
  • java.util.regex.Pattern返回由此匹配器解释的模式 java.util.regex.Matches ###regex里没有Matcher方法 尝试将整个区域与模式匹配。 如果匹配成功,则可以通过 start、end 和 group 方法获取更多信息。 返回: 当且仅当整个区域序列匹配此匹配器的模式时才返回 true。
  • java正则表达式[2023-08-29]

    ^ 和 $ 他们是分别用来匹配字符串的开始和结束,以下分别举例说明: "^The": 开头一定要有"The"字符串; "of despair$": 结尾一定要有"of despair" 的字符串; 那么, "^abc$": 就是要求以abc开头和以abc结尾的字符串,实际上是只有abc匹配。 "notice": 匹配包含notice的字符串。 你可以看见如果你没有用我们提到的两个字符(最后一个例子),就是说 模式(正则表达式) 可以出现在被检验字符串的任何地方,你没有把他锁定到两边。 接着,说说 '*', ...
  • JAVA正则表达式[2024-05-06]

    我这里有一份最基础的正则表达式的教程,要的话给我邮箱,我发给你! 对于邮箱这些的判断,你可以去搜集一下 如果你编程是用html5的话那已经自带了这些判断了!
  • http://www.ccw.com.cn/htm/app/aprog/01_7_31_4.asp 内容太多,不写了,自己去看看吧
  • 给我邮箱,我发一份资料给你,是关于正则表达式的基础,也算挺详细的!
  • package com; public class Joey { public static void main(String[] args) { String ip = "10.1.107.0/24"; String reg = "^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)/\\d+$"; System.out.println(ip.matches(reg)); } }
  • java正则表达式[2022-01-30]

    ^ 和 $ 他们是分别用来匹配字符串的开始和结束,以下分别举例说明: "^The": 开头一定要有"The"字符串; "of despair$": 结尾一定要有"of despair" 的字符串; 那么, "^abc$": 就是要求以abc开头和以abc结尾的字符串,实际上是只有abc匹配。 "notice": 匹配包含notice的字符串。 你可以看见如果你没有用我们提到的两个字符(最后一个例子),就是说 模式(正则表达式) 可以出现在被检验字符串的任何地方,你没有把他锁定到两边。 接着,说说 '*', ...
  • 我举例说明: x(?=y) ▲表示:右边紧跟y的x,但只包含x,不包含y x(?=y|z) ▲表示:右边紧跟y或z的x,但只包含x,不包含y或z x(?!y) ▲表示:右边不跟y的x,只包含x 你的这个正则表达式完全正确: ,(?=[^\"]+?\",|[^\"]+?\"$) ▲它只匹配1个, ▲▲但条件是: ▲条件1▲:此,右边到第1个",之间有至少1个不是"的字符 ▲条件2▲:此,右边到结尾的"之间有至少1个不是"的字符 举例说明: 它匹配下面3行中的前2个, (每次匹配1个,而不是同时匹配前2个) x ...
  • 就是检查字符串是否符合某个格式 看我的例子 public class Judge { public static void main(String[] args) { String a="\\w{0,}\\@?\\w{0,}\\.{1,}\\w{0,}"; String str1="aaaa@"; String str2="aaaa"; String str3="aaaaa@111.com"; if(str1.matches(a)){ System.out.println(str1+"是1个E—mail地址 ...