软件构造——正则表达式学习

以下内容均基于按照官方文档进行学习的记录官方文档传送门
正则表达式有什么作用?

Regular expressions are a way to describe a set of strings based on common characteristics shared by each string in the set. They can be used to search, edit, or manipulate text and data. You must learn a specific syntax to create regular expressions — one that goes beyond the normal syntax of the Java programming language. Regular expressions vary in complexity, but once you understand the basics of how they’re constructed, you’ll be able to decipher (or create) any regular expression.

用我蹩脚的英语理解来简单翻译下这段文字:
正则表达式基于集合中每个字符串共享的公共特征来描述一组字符串,可以用于查找、编辑、文本或数据处理。下面我们就来学习一种特殊的语法来creat正则表达式,这个和java中的通常的语法不一样。正则表达式的复杂度各不相同,但是一旦我们理解了如何构建这些正则表达式,我们就可以破译或者构建任何正则表达式。😄
了解java的正则表达式所在的包
java.util.regex包由三个类组成:Pattern,Matcher和PatternSyntaxException.

  • 一个Pattern对象是一个正则表达式编译之后的表示。Pattern这个类没有提供共有的构造函数。要创建一个Pattern对象,必须调用它的public static complie方法,这个方法会返回一个Pattern对象。这个方法接受一个正则表达式作为第一个参数。
//一个简简单单的例子,但是说明了如何生成一个Pattern对象,看不懂"^[NB]{1}[0-9]{4}$"
//没关系,只要知道compile可以生成Pattern对象,知道怎么用就好了
Pattern planeInputPattern = Pattern.compile("^[NB]{1}[0-9]{4}$");
  • 一个Matcher对象是解释Pattern并对输入的字符串执行匹配操作的工具。类似Pattern,这个Matcher也没有public的构造函数。通过对一个Pattern对象调用matcher函数生成一个Matcher对象。
Matcher matcher = planeInputPattern.matcher(planeInputString);
  • 一个patternSyntaxException对象是一个unchecked 异常,表示在正则表达式模式中出现了语法错误。
    测试工具
    当然也可以在网上找到在线测试工具
import java.io.Console;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexTestHarness {

    public static void main(String[] args){
        Console console = System.console();
        if (console == null) {
            System.err.println("No console.");
            System.exit(1);
        }
        while (true) {

            Pattern pattern = 
            Pattern.compile(console.readLine("%nEnter your regex: "));

            Matcher matcher = 
            pattern.matcher(console.readLine("Enter input string to search: "));

            boolean found = false;
            while (matcher.find()) {
                console.format("I found the text" +
                    " \"%s\" starting at " +
                    "index %d and ending at index %d.%n",
                    matcher.group(),
                    matcher.start(),
                    matcher.end());
                found = true;
            }
            if(!found){
                console.format("No match found.%n");
            }
        }
    }
}

特殊字符
使用 \将特殊字符转换成普通字符,在Java中用的是\\(第一个\是java编译器需要的,第二是正则表达式中的语法),或者是\Qxxx\E,其中xxx表示特殊字符。

表示描述
[abc]出现a、b、c中的一个即可
[^abc]任何字符,只要不是a、b、c
[a-zA-Z]表示从a到z的所有小写字母,或者从A到Z的所有大写字母中的一个
[a-d[m-p]]和[a-dm-p]意思相同
[a-z&&[def]]表示一个字符,既是a-z中的,也是[def]中的(在这个表达式中就是d或e或f,也就是前后两表达式表示集合的交集)
[a-z&&[^bc]]除了b和c之外的从a到z的任意字符(也就是前面那个集合和后面那个集合做差集)
^表示字符串的起始位置
$表示字符串的结束位置
{n}这个放在一个表达式后面,表示这个表达式出现n次,例如o{3},表示ooo
{n,m}表示从n次到m次都匹配,如果m缺省,则表示从n次到任意次都匹配
*和{0,}同意
+和{1,}同意
?和{0,1}同意
.任意字符(可能匹配也可坑不匹配行终止符)
x|y表示x或者y
\d和[0-9]同意
\D和[^0-9]同意
\s一个不可见字符,和[\t\n\x0B\f\r]同意
\S一个非空白字符
\w和[a-zA-Z_0-9]同意(表示任意大写字母、小写字母、下划线、数字)
\W和[^\w]同意

数量词
使用量词使我们可以指定匹配的次数。
下面是PatternAPI 给出的三个模式。

贪婪模式勉强模式所有格模式意思
X?X??X?+X, once or not at all
X*X*?X*+X, zero or more times
X+X+?X++X, one or more times
X{n}X{n}?X{n}+X, exactly n times
X{n,}X{n,}?X{n,}+X, at least n times
X{n,m}X{n,m}?X{n,m}+X, at least n but not more than m times

这三种量词表示之间由细微的差别。
贪婪模式:迫使匹配器在尝试第一个匹配之前读入整个输入字符串。如果第一次匹配尝试(整个输入字符串)失败,matcher将返回一个字符并再次尝试,重复该过程,直到找到匹配或没有其他字符可供返回。
勉强模式:采用和贪婪模式相反的方法:从输入字符串的开头开始,然后不情愿地一次吃掉一个字符以查找匹配的字符。最后尝试的是整个输入字符串。
最后一种模式总是吃掉整个输入字符串,尝试匹配一次(且仅一次)。与贪婪模式不同,该模式从不回退,就算是回退可以使匹配成功也不回退。
感觉这第三种模式还是有点乱

Enter your regex: .*foo // greedy quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text “xfooxxxxxxfoo” starting at index 0 and ending at index 13.

Enter your regex: .*?foo // reluctant quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text “xfoo” starting at index 0 and ending at index 4.
I found the text “xxxxxxfoo” starting at index 4 and ending at index 13.

Enter your regex: .*+foo // possessive quantifier
Enter input string to search: xfooxxxxxxfoo
No match found.

Enter your regex: a?
Enter input string to search: ababaaaab
I found the text “a” starting at index 0 and ending at index 1.
I found the text “” starting at index 1 and ending at index 1.
I found the text “a” starting at index 2 and ending at index 3.
I found the text “” starting at index 3 and ending at index 3.
I found the text “a” starting at index 4 and ending at index 5.
I found the text “a” starting at index 5 and ending at index 6.
I found the text “a” starting at index 6 and ending at index 7.
I found the text “a” starting at index 7 and ending at index 8.
I found the text “” starting at index 8 and ending at index 8.
I found the text “” starting at index 9 and ending at index 9.

这是网站上给出的有趣的例子,可以看到即使在某个位置出现的是b,也可以匹配a?。
解释一针见血,a?知识判断a存在还是不存在,不存在则开始下标和结束下标是一样的。这种匹配“出现0次a”叫做zero-length match。

Enter your regex: a{3,6} // find at least 3 (but no more than 6) a’s in a row
Enter input string to search: aaaaaaaaa
I found the text “aaaaaa” starting at index 0 and ending at index 6.
I found the text “aaa” starting at index 6 and ending at index 9.

这个例子说明,{n,m}这种限制次数的表示,也是“贪婪”的,会尽可能多进行匹配
使用量词捕获组和字符类
即[abc]+和(AB)+这种表示也是合法的。
Capturing groups:将一组输入用()括起来,表示成一个整体,可以看做一个单位。
编号
针对Capturing groups可以对其进行编号,编号规则就是:从左向右查看(,按照其出现的顺序进行编号。

表示((A)(B( C)))
1. ((A)(B( C)))
2. (A)
3. (B( C))
4. ( C)

在一个匹配器对象上调用groupCount函数就可以获得表达式中有多少组,方法返回int类型。
界限匹配符:规定匹配在字符串的那里发生。

边界构造描述
^表示一行的开始
$表示一行的结束
\b表示一个单词边界
\B表示不是一个单词边界
\A表示输入的开始
\G表示前一个匹配的结束
\Z:输入的结束,但对于最终的终止符,如果有的话
\z表示输入的结束

创建带有标志的Pattern

The Pattern class defines an alternate compile method that accepts a set of flags affecting the way the pattern is matched. The flags parameter is a bit mask that may include any of the following public static fields:

Pattern.CANON_EQ:使规范等价。使用这个标志,则当且晋档如果且仅当两各字符串的完整分解匹配的时候才会返回匹配。
Pattern.CASE_INSENSITIVE:允许匹配不区分大小写。不区分大小写的匹配也可以通过嵌入的标志表达式(?i)启用。
Pattern.COMMENTS:允许模式中有空白和注释。这样使用,将会忽略空白,并且以#开头的注释将被忽视。这种匹配可以通过(?x)实现。
Pattern.DOTALL:允许dotall模式。在这种模式中“.”匹配任何字符,包括一个行终止符。但是默认情况下“.”是不匹配行终止符的。这种匹配模式也可以通过(?s)来实现。

使用方法是Pattern.compile(“带匹配的模式”,Pattern.xxxxxxxx);
Pattern的其他实用方法
public boolean matches(String regex): 判断字符串和给定的模式是否匹配。

  • str.matches(regex)
  • Pattern.matches(regex, str)
    public String[] split(String regex, int limit): 将字符串按照给定的模式进行拆分。
    public String[] split(String regex):功能同上。
    public String replace(CharSequence target,CharSequence replacement):将符合target中给出的模式的部分替换为replacement)
    Matcher的其他实用方法
    public int start(): 返回上一个匹配开始索引。
    public int end(): Returns the offset after the last character matched.
    public int start(int group):返回给定组在前一个匹配操作期间捕获的子序列的开始索引。
    public int end(int group): Returns the offset after the last character of the subsequence captured by the given group during the previous match operation.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值