javaz正则、捕获组

java正则、捕获组

1.正则概念

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。

2.正则表达式的规则

> 1、任意一个字符表示匹配任意对应的字符,如a匹配a,7匹配7-匹配-> 
> 2[]代表匹配中括号中其中任一个字符,如[abc]匹配a或b或c。
> 
> 3-在中括号里面和外面代表含义不同,如在外时,就匹配-,如果在中括号内[a-b]表示匹配26个小写字母中的任一个;[a-zA-Z]匹配大小写共52个字母中任一个;[0-9]匹配十个数字中任一个。
> 
> 4^在中括号里面和外面含义不同,如在外时,就表示开头,  ^ 7[0-9]表示匹配开头是7的,且第二位是任一数字的字符串;如果在中括号里面,表示除了这个字符之外的任意字符(包括数字,特殊字符),如[^abc]表示匹配出去abc之外的其他任一字符。


> 5.表示匹配任意的字符。
> 6、\d表示数字。
> 7、\D表示非数字。
> 8、\s表示由空字符组成,[ \t\n\r\x\f]> 9、\S表示由非空字符组成,[^\s]> 10、\w表示字母、数字、下划线,[a-zA-Z0-9_]> 11、\W表示不是由字母、数字、下划线组成。

> 12?: 表示出现0次或1> 13+表示出现1次或多次。
> 14*表示出现0次、1次或多次。
> 15{n}表示出现n次。
> 16{n,m}表示出现n~m次。
> 17{n,}表示出现n次或n次以上。
> 18、XY表示X后面跟着Y,这里XY分别是正则表达式的一部分。
> 19X|Y表示XY,比如"food|f"匹配的是foo(d或f),而"(food)|f"匹配的是food或f。
> 20(X)子表达式,将X看做是一个整体。

3.如何使用正则表达式

3.1 匹配

1). 实现方式1,匹配一个数字。

   /**
     * 匹配一个数字
     */
    public void regex1(){
        String str = "8";
        String regex = "[0-9]";
        boolean flag = Pattern.matches(regex,str);
        System.out.println(flag);
    }

2). 实现方式2, 匹配3个到5个字母,大小写不限,包括3和5个。

    /**
     * 匹配3到5个字母
     */
    public void regex2(){
        String str = "hello";
        String regex = "[a-zA-Z]{3,5}";
        boolean flag = Pattern.matches(regex,str);
        System.out.println(flag);
    }

3). 实现方式3(此种实现方式最快), 匹配11位的电话号码,匹配规则:第一个数字是1,第二个数字是2,3,7,8中任一个,后面9位数字中不包含4。

   /**
     * 匹配11位的电话号码,匹配规则:第一个数字是1,第二个数字是2,3,7,8中任一个,后面9位数字中不包含4。
     */
    public void regex3(){
        String str = "13656231253";
        String regex = "1[2378][0-35-9]{9}";
        boolean flag = Pattern.matches(regex,str);
        System.out.println(flag);
    }

4)正则必须包含字母数字下划线,长度至少8位

思路:排除法

1、排除大写字母、小写字母、数字、特殊符号中1种组合、2种组合、3种组合,那么就只剩下4种都包含的组合了

2、表达式为:^(?![A-Za-z0-9]+)(?![a−z0−9W]+)(?![a-z0-9\\W]+)(?![az09W]+)(?![A-Za-z\W]+)(?![A−Z0−9W]+)(?![A-Z0-9\\W]+)(?![AZ09W]+)[a-zA-Z0-9\W]{8,}$

3、拆分解释:其中(2)-(6)运用了零宽断言、环视等正则功能

(1)^匹配开头

(2)(?![A-Za-z0-9]+$)匹配后面不全是(大写字母或小写字母或数字)的位置,排除了(大写字母、小写字母、数字)的1种2种3种组合

(3)(?![a-z0-9\W]+$)同理,排除了(小写字母、数字、特殊符号)的1种2种3种组合

(4)(?![A-Za-z\W]+$)同理,排除了(大写字母、小写字母、特殊符号)的1种2种3种组合

(5)(?![A-Z0-9\W]+$)同理,排除了(大写字母、数组、特殊符号)的1种2种3种组合

(6)[a-zA-Z0-9\W]匹配(小写字母或大写字母或数字或特殊符号)因为排除了上面的组合,所以就只剩下了4种都包含的组合了

(7){8,}8位以上

(8)$匹配字符串结尾

代码:

 //大小写字母数字下划线4选4,且至少8位
 private final String regex4 = "^(?![A-Z0-9\\W_]+$)(?![a-z0-9\\W_]+$)(?![a-zA-Z\\W_]+$)(?![a-zA-Z0-9]+$)[a-zA-Z0-9\\W_]{8,}$";
 //大小写字母数字下划线4选3,且至少8位
 private final String regex4To3 = "^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_]+$)(?![a-z0-9]+$)(?![a-z\\W_]+$)(?![0-9\\W_]+$)[a-zA-Z0-9\\W_]{8,}$";
 //大小写字母数字下划线,且至少8位
 private final String regexAll = "[a-zA-Z0-9\\W_]{8,}";
/**
     * 正则必须包含字母数字下划线,长度至少8位
     * @param str1
     * @return
     */
    public boolean regex5(String str1){
        boolean flag = false;
        flag = Pattern.matches(regex4,str1);
        return flag;
    }

3.2 替换

1)简单替换

   /**
     * 替换数字、字母
     */
    public void regex4(){
        String str = "12ab8cde9fg0";
        String regex1 = "[a-zA-Z]";
        String regex2 = "\\d+";
        String regex1Replace = str.replaceAll(regex1,".");
        String regex2Replace = str.replaceAll(regex2,"*");
        System.out.println(regex1Replace);
        System.out.println(regex2Replace);
    }

4 、捕获组

捕获组分为:

普通捕获组(Expression)
命名捕获组(?Expression)

普通捕获组

从正则表达式左侧开始,每出现一个左括号"("记做一个分组,分组编号从 1 开始。0 代表整个表达式。

对于时间字符串:2017-04-25,表达式如下

(\\d{4})-((\\d{2})-(\\d{2}))

有 4 个左括号,所以有 4 个分组:

编号捕获组匹配
0(\d{4})-((\d{2})-(\d{2}))2017-04-25
1(\d{4}) 2017
2((\d{2})-(\d{2}))04-25
3(\d{2}) 04
4(\d{2}) 25
代码
   public void regex6(){
        //捕获组
        String DATE_STRING = "2017-04-25";
        String P_COMM = "(\\d{4}-((\\d{2})-(\\d{2})))";

        Pattern pattern = Pattern.compile(P_COMM);
        Matcher matcher = pattern.matcher(DATE_STRING);
        matcher.find();//必须要有这句
        System.out.printf("\nmatcher.group(0) value:%s", matcher.group(0));
        System.out.printf("\nmatcher.group(1) value:%s", matcher.group(1));
        System.out.printf("\nmatcher.group(2) value:%s", matcher.group(2));
        System.out.printf("\nmatcher.group(3) value:%s", matcher.group(3));
        System.out.printf("\nmatcher.group(4) value:%s", matcher.group(4));
    }

结果

命名捕获组

每个以左括号开始的捕获组,都紧跟着 ?,而后才是正则表达式。

对于时间字符串:2017-04-25,表达式如下:

(?<year>\\d{4})-(?<md>(?<month>\\d{2})-(?<date>\\d{2}))

命名的捕获组同样也可以使用编号获取相应值。

    public void regex7(){
        String DATE_STRING = "2017-04-25";
        String P_COMM = "(?<year>\\d{4})-(?<md>(?<mm>\\d{2})-(?<dd>\\d{2}))";
        Pattern pattern = Pattern.compile(P_COMM);
        Matcher matcher = pattern.matcher(DATE_STRING);
        matcher.find();//必须要有这句
        System.out.printf("\nmatcher.group(0) value:%s", matcher.group(0));
        System.out.printf("\nmatcher.group(1) value:%s", matcher.group("year"));
        System.out.printf("\nmatcher.group(2) value:%s", matcher.group("md"));
        System.out.printf("\nmatcher.group(3) value:%s", matcher.group("mm"));
        System.out.printf("\nmatcher.group(4) value:%s", matcher.group("dd"));
    }

在这里插入图片描述

菜鸟教程地址:https://www.runoob.com/java/java-regular-expressions.html
参考地址:https://www.jianshu.com/p/3c076c6b2dc8

<think>好的,我现在需要解决用户关于Nginx正则捕获组语法以及在server_name中使用捕获组映射SSL证书路径的问题。首先,我应该回顾一下Nginx的正则表达式语法,特别是捕获组的用法。 用户提到的是在server_name中使用正则捕获组,并正确映射SSL证书路径。我记得Nginx的server_name支持通配符和正则表达式,但正则表达式需要以波浪线开头,比如~。捕获组是通过圆括号来定义的,这和常规的正则表达式语法一致。例如,server_name ~^(www\.)?(.+)$; 这里有两个捕获组,第一个匹配可选的www.,第二个匹配域名的主体部分。 接下来是如何将这些捕获组应用到SSL证书的路径中。通常,证书和私钥的路径是固定的,但如果需要动态生成路径,可能需要使用变量。比如,如果域名是通过捕获组获取的,可能可以用$1、$2等变量来引用这些组。例如,ssl_certificate /path/to/certs/$2.crt; 这里的$2就是第二个捕获组的内容,对应域名的主体部分。 但需要注意的是,Nginx在配置加载时就会解析这些路径,所以必须确保所有可能的捕获组对应的证书文件都存在,否则Nginx启动时会报错。此外,通配符证书可能需要使用不同的配置,比如*.example.com的通配符证书,这时候可能不需要捕获组,直接用通配符即可。但用户的情况可能涉及多个子域名,每个子域名需要不同的证书,这时候正则捕获组就能派上用场。 举个例子,假设有多个子域名,如app1.example.com、app2.example.com,每个都有自己的证书。可以配置server_name为~^app(\d+)\.example\.com$,然后ssl_certificate设置为/app$1.crt,这样就能动态匹配不同的证书。但必须确保每个app1、app2对应的证书文件存在。 另外,用户可能遇到的问题包括正则表达式编写错误,导致捕获组无法正确匹配;证书路径不正确,Nginx无法找到文件;或者变量在配置中的使用不正确。需要提醒用户检查正则表达式是否正确,变量是否引用正确,以及证书文件是否存在。 还需要参考用户提供的引用内容,看看是否有相关的配置示例。例如,在引用[3]中,有多个server块的配置,每个server_name对应不同的子域名,并设置了不同的root路径。类似地,可以借鉴这种结构,在SSL证书的路径中使用捕获组变量。 总结步骤应该是:首先编写正确的正则表达式server_name,使用捕获组提取所需部分;然后在ssl_certificate和ssl_certificate_key指令中使用这些捕获组的变量;最后确保所有可能的证书文件路径正确存在。同时,注意Nginx在启动时验证证书路径,因此需要提前部署好所有证书文件。</think>### Nginx正则捕获组在SSL证书映射中的应用 在Nginx配置中,正则捕获组可以用于动态匹配域名并映射对应的SSL证书路径。以下是具体实现方法: #### 1. 正则捕获组语法 - **基本格式**:`server_name`中使用正则表达式需以`~`开头,例如: ```nginx server_name ~^(?<subdomain>\w+)\.example\.com$; ``` 这里使用命名捕获组`?<subdomain>`,匹配子域名部分(如`api`或`admin`),也可使用数字索引如`$1`[^3]。 #### 2. SSL证书路径映射 通过捕获组变量动态指定证书路径: ```nginx server { listen 443 ssl; server_name ~^(?<sub>[a-z]+)\.example\.com$; # 匹配子域名 ssl_certificate /etc/ssl/certs/$sub.crt; # 使用捕获组变量 ssl_certificate_key /etc/ssl/private/$sub.key; ... } ``` 此配置会为`api.example.com`加载`/etc/ssl/certs/api.crt`证书,为`admin.example.com`加载`/etc/ssl/certs/admin.crt`。 #### 3. 注意事项 - **证书文件预部署**:必须提前为所有可能的子域名生成并部署证书文件,否则Nginx启动失败。 - **正则表达式优化**:避免过于宽泛的匹配(如`.*`),可能导致安全风险或配置冲突。 - **通配符证书替代方案**:若使用通配符证书`*.example.com`,可直接配置: ```nginx ssl_certificate /etc/ssl/wildcard.example.com.crt; ssl_certificate_key /etc/ssl/wildcard.example.com.key; ``` #### 4. 完整示例 ```nginx server { listen 443 ssl; server_name ~^(\w+)\.example\.com$; # 数字索引捕获组 ssl_certificate /certs/$1/fullchain.pem; # $1对应子域名 ssl_certificate_key /certs/$1/privkey.pem; ssl_prefer_server_ciphers on; # 启用服务器密码优先级[^1] ... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值