Java 正则表达式

基本语法

元字符

  • 转义号 \\
限定符
符号 含义
* 指定前面内容可以出现 0次及以上
+ 指定前面内容可以出现 1次及以上。至少会出现一次
? 指定前面内容可以出现 0次或一次
{n} 指定前面的内容 只能出现n次
{n,} 指定前面内容 至少出现n次
{n, m} 指定前面内容 至少出现n次但不多于m次
选择匹配符
符号 解释
| 逻辑或的含义,符号两边内容有一个成立即可 |
分组组合和反向引用符
  • 分组
常用分组构造形式 说明
(pattern) 非命名捕获。捕获匹配的子字符串。编号为0的第一个捕获是由整个正则表达式模式匹配的文本,其它捕获结果则根据左括号的顺序从1开始自动编号
(?pattern) 命名捕获。将匹配的子字符串捕获到一个组名或编号名中。用于name的字符串不能包含任何标点符号,并且不能以数字开头。可以使用单引号代替尖括号
  • 非捕获分组
常用分组构造形式 说明
(?:pattern) 匹配pattern,但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供后续使用。这对于 or 字符 | 组合模式的部件情况很有用。
例如 industr(?:y|ies) 是比 industry|industries更经济的表达式。
(?=pattern) 它是一个非捕获匹配。
例如,Windows (?=95|98|2000) 匹配 Windows 2000 中的 Windows,但不匹配 Windows 2008 中的 Windows
(?!pattern) 该表达式匹配不处于匹配 pattern 的字符串的起始点的搜索字符串。他是一个非捕获匹配。功效与 (?=pattern)相反
特殊字符
元字符 含义
$ 匹配行的结尾
^ 匹配行的开头
* 指定前面内容可以出现 0次及以上
+ 指定前面内容可以出现 1次及以上。至少会出现一次
? 指定前面内容可以出现 0次或一次
. 代指单个除了换行符之外的任意字符
\ 用来转义一些特殊字符
| 逻辑或的含义,符号两边内容有一个成立即可
{} () [] 三种括号都有其特定的含义

java 中使用 \\\\ 来表示单个 \

字符匹配符
符号 示例 解释
[ ] [abc] 表示abc中任意一个字符
[^ ] [abc] 表示除了abc之外的所有其它任意一个字符
[ - ] [A-Z] 连字符,表示 A 到 Z 之间的任意一个大写字母
. a..b 匹配除了 \n 以外的任意字符
\\d \\d{3}(\\d)? 匹配单个数字。示例表示包含 3、4个数字
\\D \\D(\\d)* \\d 相反。示例表示任意非数字开始后边有任意个数字的组合
\\w \\d{3}\\w* 表示匹配单个数字、大小写英文字母、下划线的字符。
\\W \\W 相反。
\\s 匹配任意空白的字符,包括制表符,换行符等
\\S \\s 相反
定位符
符号 含义
^ 匹配行的开头
$ 匹配行的结尾
\\b 匹配目标字符串的边界
\\B 匹配目标字符串的非边界

分组、捕获与反向引用

找出所有四个数字连在一起的子串,并且这四个数字满足第一位与第四位相同,第二位与第三位相同

  • 分组:用圆括号组成一个比较复杂的匹配模式,那么一个圆括号的部分可以看作使一个子表达式一个分组

  • 捕获:把正则表达式中子表达式/分组匹配的内容。保存到内存中以数字为编号或命名的组里,方便后边引用,从左往右,以分组的左括号为标志,第一个出现的组为1,第二个为2…组0则是整个正则表达式匹配的内容

  • 反向引用:圆括号的内容被捕获后,可以在这个括号后被使用,从而写出一个比较使用的匹配模式,这个称为反向引用,这种引用既可以是在正则表达式内部,也可以在正则表达式外部,内部反向引用\\分组号,外部分组引用 $分组号

    • 内部反向引用:使用 \\分组号 来使用前边捕获到的分组内容

      1. 匹配两个连续相同的数字 (\\d)\\1

      2. 匹配五个连续相同的数字 (\\d)\\1{4}

      3. 匹配个位与千位相同,十位与百位相同的四位数 (\\d)(\\d)\\2\\1

    • 外部分组引用:使用 $分组号 在外部使用捕获到的分组内容

    String str = "11333323467";
    // 匹配表示匹配至少有一个重复的内容,如22,333,aaaa 等
    Pattern pattern = Pattern.compile("(\\d)\\1+");
    Matcher matcher = pattern.matcher(str);
    // 用捕获分组1的内容 替换所有匹配到的内容
    str = matcher.replaceAll("$1");
    // 上面的语句可以等价于  
    // while (matcher.find()) {
    //     str = str.replace(matcher.group(0), matcher.group(1));
    // }
    System.out.println(str);  // 结果: 1323467
    

实例

匹配不区分大小写

  • (?i)abc 表示 abc 都不区分大小写
  • a(?i)bc 表示 bc 都不区分大小写
  • a((?i)b)c 表示只有 b 不区分大小写
// Java 代码中实现
Pattern.compile(regex, Pattern.CASE_INSENSITIVE)

贪婪匹配

String str = "aaaaaa"; // 6个a
Pattern pattern = Pattern.compile("a{3,4}");
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
    System.out.println(matcher.group(0));
}
// 此时的输出结果只有一个 aaaa 而不是两个 aaa aaa

非贪婪匹配

? ,此字符紧随任何其它限定符 *、+、?、{n}、{n,m} 之后时,匹配的模式是非贪婪匹配

非贪婪匹配:匹配搜索到的、尽可能短的字符串

+?*? 意义与区别
  • +? 表示匹配前面的内容一个或多个

  • *? 表示匹配前面的内容0个或多个

代码比对
String content = "111111aaa";
String regex = "";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(content);
while (matcher.find()) {
    System.out.println("找到结果: " + matcher.group(0));
}

下边都使用上述代码,只是每次的正则表达式不一致

  • 使用 regex = "[1a]+"

找到结果: 111111aaa

  • 使用 regex = "[1a]*"

找到结果: 111111aaa
找到结果:

  • 使用 regex = [1a]?

找到结果: 1
找到结果: 1
找到结果: 1
找到结果: 1
找到结果: 1
找到结果: 1
找到结果: a
找到结果: a
找到结果: a
找到结果:

  • 使用 regex = [1a]+?

找到结果: 1
找到结果: 1
找到结果: 1
找到结果: 1
找到结果: 1
找到结果: 1
找到结果: a
找到结果: a
找到结果: a

  • 使用 regex = [1a]*?

找到结果:
找到结果:
找到结果:
找到结果:
找到结果:
找到结果:
找到结果:
找到结果:
找到结果:
找到结果:

验证汉字

使用 [\u0391-\uffe5] 来匹配任意单个汉字

验证url

^(http[s]?://)([\w-]+\.)+([\w]){2,}(:\d{1,5})?(/[\w-#%]+)*(/[\w-#%]+.\w+)?\??([\w-%._#]+=[\w%._#]+&?)*$

在 [ ] 中的内容

将一些特殊元字符放在 [] 中时,相当于使用 \\ 对其进行转义

  • 例如:[.] 等价与 \\.

结巴程序

String str = "我我要学学学学编程Java";
Pattern pattern = Pattern.compile("(.)(\\1)+");
Matcher matcher = pattern.matcher(str);
// while (matcher.find()) {
    // str = str.replace(matcher.group(0), matcher.group(1));
// }
content = matcher.replceAll("$1");
System.out.println(str);

验证邮件地址

^[\\w.-_]+@([\\w-_]+\\.)+(\\w){2,}$

验证整数或小数,有正负

^(-+)?([1-9]\\d*|0)(\\.\\d+)?$

你可能感兴趣的:(Java,java,正则表达式)