[学习笔记]Java正则表达式



1. 概述

正则表达式是用于描述字符串复杂规则的工具,换句话说,正则表达式就是记录文本规则的代码。

2. 优势与劣势

优势:用了一些符号来代表这些代码,书写起来更为简单。
劣势:因为都是一些符号组成的表达式,所以阅读起来可读性不高,而且先要把符号学完。

3. 格式

3.1 元字符

  • .    匹配除换行符以外的任意字符
  • \w   匹配字母或数字或下划线或汉字
  • \s   匹配任意的空白符
  • \d   匹配数字
  • \b   匹配单词的开始或结束
  • ^    匹配字符串的开始
  • $    匹配字符串的结束
示例
  • \b\w\w\b:匹配由2个字母构成的单词。(Java字符串中为"\\b\\w\\w\\b")

3.2 限定符

  • *     重复零次或更多次
  • +     重复一次或更多次
  • ?     重复零次或一次
  • {n}   重复n次
  • {n,}  重复n次或更多次
  • {n,m} 重复n到m次
示例
  • \ba\w*\b:匹配以字母a开头的单词。(Java字符串中为"\\ba\\w*\\b")
  • \d+:匹配1个或更多连续的数字。(Java字符串中为"\\d+")
  • \b\w{6}\b:匹配刚好6个字符的单词。(Java字符串中为"\\b\\w{6}\\b")

3.3 字符与字符转义

  • 单个字符的判断可以使用集合概念,只需使用"[]"即可,例如:"[aeiou]"匹配任何一个英文元音字母。
  • 在Java字符串中,由于字符"\"本身具有转义性,所以凡是带有"\"的正则表达式,均需要使用"\\"来替代"\"。例如上述例子"\d+"在Java字符串中应写成"\\d+"。
  • 如果需要匹配正则表达式中有特殊意义的字符本身,需要使用"\"进行转义。例如可以使用正则表达式"\\w*\.\\w*"来匹配"abc.com"。
示例
  • \(?0\d{2,3}[) -]?\d{7,8}:匹配几种格式的电话号码,类似(010)88886666,或0554-22334455,或05541234567等。

3.4 分支条件(逻辑或)

  • 如果多种情况需要匹配,可以使用"|"将多种正则表达式连接在一起成为一个,任何满足其中一个正则表达式即可匹配。
示例
  • 0\d{2}-\d{8}|0\d{3}-\d{7}:匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)。

3.5 分组

  • 如果需要对多个字符进行重复或者在Java字符串中进行替换处理,可以使用分组,符号为"()"。
  • Java字符串处理中,使用"\数字"来代替前面的第几个分组,例如"(.)\\1+"匹配出现连续相同字符。
示例
  • (\d{1,3}\.){3}\d{1,3}:简单的IP地址匹配表达式,但是类似"111.222.666.999"的IP地址也视为匹配。
  • ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?):IP地址匹配表达式,由于正则表达式不支持数学运算和比较,所以只能使用繁杂的分组和分支来实现。

3.6 反义

  • \W       匹配任意不是字母,数字,下划线,汉字的字符
  • \S       匹配任意不是空白符的字符
  • \D       匹配任意非数字的字符
  • \B       匹配不是单词开头或结束的位置
  • [^x]     匹配除了x以外的任意字符
  • [^aeiou] 匹配除了aeiou这几个字母以外的任意字符
示例
  • \S+:匹配不包含空白符的字符串。

字符串(String类)

1. 匹配

方法

  • boolean  matches(String regex)

示例

   
   
String num = "13988887777\nhaha";
String numRegex = "[1][3578]\\d{9}"; // 匹配手机号码
boolean b = num .matches(numRegex );

2. 分割

方法

  • String[]  split(String regex)
  • String[]  split(String regex, int limit)

示例

   
   
public static void split() {
String str1 = "itheima.java.jacob.meteor";
// 按“.”分割字符串
String regex1 = "\\.";
 
String str2 = "itheima java jacob \tmeteor";
// 按空白字符分割字符串
String regex2 = "\\s+";
 
String str3 = "itheimaeeejava$$jacoboooometeor";
// 按重复字符分割字符串
String regex3 = "(.)\\1+";
 
split (str1 , regex1 );
split (str2 , regex2 );
split (str3 , regex3 );
}
 
public static void split(String str, String regex) {
String[] arr = str.split(regex);
for (String string : arr ) {
System.out.print( string + " | ");
}
System.out.println();
}

3. 替代

方法

  • String  replaceAll(String regex, String replacement)
  • String  replaceFirst(String regex, String replacement)

示例

   
   
String str1 = "itheima######java&&&&&&&meteor";
// 将将叠词替换成"-"
str1 = str1 .replaceAll("(.)\\1+" , "-" );
 
String str2 = "itheima######java&&&&&&&meteor";
// 将将叠词替换成其中的一个,多个######用#替换。
// 当在第二个参数中使用第一个正则参数中的组时,可以使用$编号来完成组的调用。\\1只能使用在正则表达式中。
str2 = str2 .replaceAll("(.)\\1+" , "$1" );
 
String str3 = "13988887777";
// 将电话中的中间四位替换成****;
str3 = str3 .replaceAll("(\\d{3})(\\d{4})(\\d{4})" , "$1****$3");

正则表达式相关API

1. Pattern类(java.util.regex)

概述

正则表达式的编译表现形式,每一个正则表达式在编译后都是一个Pattern对象。该类无构造器,使用静态方法编译正则表达式获取实例。Pattern的作用是将正则字符串封装成正则对象。

方法

  • 编译正则表达式
    static Pattern  compile(String regex)
  • 按正则表达式获取匹配输入的匹配器
    Matcher  matcher(CharSequence input)
  • 按给定正则表达式匹配字符序列
    static boolean  matches(String regex, CharSequence input)
  • 获取该正则表达式
    String  pattern()
  • 按正则表达式分割字符序列
    String[]  split(CharSequence input)
    String[]  split(CharSequence input, int limit)

2. Matcher类(java.util.regex)

概述

字符串与正则表达式的匹配表现形式,起作用就是将字符串和正则表达式的匹配封装成对象。该类无构造器,一般通过Pattern类实例创建匹配器实例。

方法

  • 匹配下一处
    boolean  find()
  • 重置匹配器,从start开始匹配下一处
    boolean  find(int start)
  • 获取先前已经匹配的字符串
    String  group()
  • 获取匹配成功的次数
    int  groupCount()
  • 从区域开头开始匹配
    boolean  lookingAt()
  • 整个区域进行匹配
    boolean  matches()
  • 获取该匹配器的正则表达式对象
    Pattern  pattern()
  • 对匹配器的区域进行限制
    Matcher  region(int start, int end)
  • 全部替换
    String  replaceAll(String replacement)
  • 替换匹配第一处
    String  replaceFirst(String replacement)
  • 重置匹配器
    Matcher  reset()
  • 使用新的字符序列重置匹配器
    Matcher  reset(CharSequence input)
  • 获取上一次匹配的开始索引
    int  start()

3. 匹配步骤

  • 将正则表达式的字符串格式先通过Pattern中的compile方法编译成Pattern正则表达式对象。
    Pattern p = Pattern.compile("a*b");
  • 要想用这个规则对字符串进行操作,还需要通过正则对象matcher方法和指定的字符串关联,并获取匹配器对象Matcher。
    Matcher m = p.matcher("aaaaab");
  • 用匹配器对象Matcher的功能(方法)对字符串进行操作。
    一般使用matches(),find(),lookingAt(),start(),end(),等方法。

4. 示例

   
   
package regex;
 
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class PatternDemo {
 
public static void main(String[] args) {
 
// 需求:获取字符串中由10个字母及以上组成的单词。
 
String str =
"Backslashes within string literals in Java source code are interpreted as required "
+ "by The Java Language Specification as either Unicode escapes (section 3.3) or other "
+ "character escapes (section 3.10.6) It is therefore necessary to double backslashes "
+ "in string literals that represent regular expressions to protect them from "
+ "interpretation by the Java bytecode compiler. The string literal b, "
+ "for example, matches a single backspace character when interpreted as a regular "
+ "expression, while b matches a word boundary. The string literal (hello) is illegal "
+ "and leads to a compile-time error; in order to match the string (hello) the string "
+ "literal (hello) must be used.";
 
// 定义规则。
String regex = "\\b[a-zA-Z]{10,}\\b";
 
// 1. 将正则字符串编译成正则对象。
Pattern p = Pattern.compile(regex );
 
// 2. 将正则对象和字符串相关联,并获取匹配器。
Matcher m = p.matcher(str);
 
// 3. 使用find的方法
/*
* m.lookingAt()方法从头匹配正则表达式一次。
* m.start()和m.end()分别能够获取匹配字符串的头尾索引值。
*/
while ( m.find()) {
System.out.println( m.group());
}
}
}

案例

1. 常见匹配

   
   
package regex;
 
import java.util.Arrays;
 
public class Text_Regex {
 
public static void main(String[] args) {
// 需求1:匹配电子邮箱
matchEmail();
 
/*
* 需求2:
* 把“我我.....我我.我....我.要.要要.....要.要学....学...学学....学.学编..编....编..编.编.程程.程...
* ..程.程程”
* 还原成:我要学编程。
*/
replace();
 
/*
* 需求3:
* 127.0.0.1 3.3.3.3 192.168.104.23 10.10.10.10
* 要求按照 ip地址的分类进行从小到大的排序。
*/
sortIP();
}
 
public static void sortIP() {
/*
* 思路:
* 由于需要按照数字排序,而字符串排序方式为字典顺序排序,所以先补零以获得同等长度IP地址字符串,再排序,最后还原。
*/
String ip = "127.0.0.1 3.3.3.3 192.168.104.23 10.10.10.10";
ip = ip.replaceAll( "(\\d+)", "00$1" );
ip = ip.replaceAll( "0*(\\d{3})", "$1" );
String[] ips = ip.split("\\s+");
Arrays.sort(ips );
for (String string : ips) {
string = string.replaceAll( "0*(\\d+)", "$1" );
System.out.println( string);
}
}
 
public static void replace() {
String str = "我我.....我我.我....我.要.要要.....要.要学....学...学学....学.学编..编....编..编.编.程程.程.....程.程程" ;
str = str.replaceAll( "\\.+", "" );
str = str.replaceAll( "(.)\\1+", "$1" );
System.out.println( str);
}
 
public static void matchEmail() {
String email = "jacobvv@163.com";
String regex = "\\w+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}" ;
boolean b = email.matches( regex);
System.out.println( b);
}
}

2. 网络爬虫

   
   
package regex;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class Text_NetSpider {
 
public static void main(String[] args) {
/*
* 需求:网络爬虫
* 获取某网页上的所有邮箱地址
*/
String url = "http://tieba.baidu.com/p/2720132008";
Set<String> email = null;
try {
email = getEmail(url );
} catch (IOException e) {
e.printStackTrace();
}
for (String string : email) {
System.out.println( string);
}
}
 
public static Set<String> getEmail(String urlStr ) throws IOException {
Set<String> email = new HashSet<String>();
String regex = "\\w+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}" ;
Pattern p = Pattern.compile(regex );
URL url = new URL( urlStr);
URLConnection conn = url.openConnection();
BufferedReader br = new BufferedReader( new InputStreamReader(conn.getInputStream()));
String content = null;
while (( content = br.readLine()) != null) {
Matcher m = p.matcher(content);
while ( m.find()) {
email.add( m.group());
}
}
br.close();
return email;
}
}

1. 概述

正则表达式是用于描述字符串复杂规则的工具,换句话说,正则表达式就是记录文本规则的代码。

2. 优势与劣势

优势:用了一些符号来代表这些代码,书写起来更为简单。
劣势:因为都是一些符号组成的表达式,所以阅读起来可读性不高,而且先要把符号学完。

3. 格式

3.1 元字符

  • .    匹配除换行符以外的任意字符
  • \w   匹配字母或数字或下划线或汉字
  • \s   匹配任意的空白符
  • \d   匹配数字
  • \b   匹配单词的开始或结束
  • ^    匹配字符串的开始
  • $    匹配字符串的结束
示例
  • \b\w\w\b:匹配由2个字母构成的单词。(Java字符串中为"\\b\\w\\w\\b")

3.2 限定符

  • *     重复零次或更多次
  • +     重复一次或更多次
  • ?     重复零次或一次
  • {n}   重复n次
  • {n,}  重复n次或更多次
  • {n,m} 重复n到m次
示例
  • \ba\w*\b:匹配以字母a开头的单词。(Java字符串中为"\\ba\\w*\\b")
  • \d+:匹配1个或更多连续的数字。(Java字符串中为"\\d+")
  • \b\w{6}\b:匹配刚好6个字符的单词。(Java字符串中为"\\b\\w{6}\\b")

3.3 字符与字符转义

  • 单个字符的判断可以使用集合概念,只需使用"[]"即可,例如:"[aeiou]"匹配任何一个英文元音字母。
  • 在Java字符串中,由于字符"\"本身具有转义性,所以凡是带有"\"的正则表达式,均需要使用"\\"来替代"\"。例如上述例子"\d+"在Java字符串中应写成"\\d+"。
  • 如果需要匹配正则表达式中有特殊意义的字符本身,需要使用"\"进行转义。例如可以使用正则表达式"\\w*\.\\w*"来匹配"abc.com"。
示例
  • \(?0\d{2,3}[) -]?\d{7,8}:匹配几种格式的电话号码,类似(010)88886666,或0554-22334455,或05541234567等。

3.4 分支条件(逻辑或)

  • 如果多种情况需要匹配,可以使用"|"将多种正则表达式连接在一起成为一个,任何满足其中一个正则表达式即可匹配。
示例
  • 0\d{2}-\d{8}|0\d{3}-\d{7}:匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)。

3.5 分组

  • 如果需要对多个字符进行重复或者在Java字符串中进行替换处理,可以使用分组,符号为"()"。
  • Java字符串处理中,使用"\数字"来代替前面的第几个分组,例如"(.)\\1+"匹配出现连续相同字符。
示例
  • (\d{1,3}\.){3}\d{1,3}:简单的IP地址匹配表达式,但是类似"111.222.666.999"的IP地址也视为匹配。
  • ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?):IP地址匹配表达式,由于正则表达式不支持数学运算和比较,所以只能使用繁杂的分组和分支来实现。

3.6 反义

  • \W       匹配任意不是字母,数字,下划线,汉字的字符
  • \S       匹配任意不是空白符的字符
  • \D       匹配任意非数字的字符
  • \B       匹配不是单词开头或结束的位置
  • [^x]     匹配除了x以外的任意字符
  • [^aeiou] 匹配除了aeiou这几个字母以外的任意字符
示例
  • \S+:匹配不包含空白符的字符串。

字符串(String类)

1. 匹配

方法

  • boolean  matches(String regex)

示例

    
    
String num = "13988887777\nhaha";
String numRegex = "[1][3578]\\d{9}"; // 匹配手机号码
boolean b = num .matches(numRegex );

2. 分割

方法

  • String[]  split(String regex)
  • String[]  split(String regex, int limit)

示例

    
    
public static void split() {
String str1 = "itheima.java.jacob.meteor";
// 按“.”分割字符串
String regex1 = "\\.";
 
String str2 = "itheima java jacob \tmeteor";
// 按空白字符分割字符串
String regex2 = "\\s+";
 
String str3 = "itheimaeeejava$$jacoboooometeor";
// 按重复字符分割字符串
String regex3 = "(.)\\1+";
 
split (str1 , regex1 );
split (str2 , regex2 );
split (str3 , regex3 );
}
 
public static void split(String str, String regex) {
String[] arr = str.split(regex);
for (String string : arr ) {
System.out.print( string + " | ");
}
System.out.println();
}

3. 替代

方法

  • String  replaceAll(String regex, String replacement)
  • String  replaceFirst(String regex, String replacement)

示例

    
    
String str1 = "itheima######java&&&&&&&meteor";
// 将将叠词替换成"-"
str1 = str1 .replaceAll("(.)\\1+" , "-" );
 
String str2 = "itheima######java&&&&&&&meteor";
// 将将叠词替换成其中的一个,多个######用#替换。
// 当在第二个参数中使用第一个正则参数中的组时,可以使用$编号来完成组的调用。\\1只能使用在正则表达式中。
str2 = str2 .replaceAll("(.)\\1+" , "$1" );
 
String str3 = "13988887777";
// 将电话中的中间四位替换成****;
str3 = str3 .replaceAll("(\\d{3})(\\d{4})(\\d{4})" , "$1****$3");

正则表达式相关API

1. Pattern类(java.util.regex)

概述

正则表达式的编译表现形式,每一个正则表达式在编译后都是一个Pattern对象。该类无构造器,使用静态方法编译正则表达式获取实例。Pattern的作用是将正则字符串封装成正则对象。

方法

  • 编译正则表达式
    static Pattern  compile(String regex)
  • 按正则表达式获取匹配输入的匹配器
    Matcher  matcher(CharSequence input)
  • 按给定正则表达式匹配字符序列
    static boolean  matches(String regex, CharSequence input)
  • 获取该正则表达式
    String  pattern()
  • 按正则表达式分割字符序列
    String[]  split(CharSequence input)
    String[]  split(CharSequence input, int limit)

2. Matcher类(java.util.regex)

概述

字符串与正则表达式的匹配表现形式,起作用就是将字符串和正则表达式的匹配封装成对象。该类无构造器,一般通过Pattern类实例创建匹配器实例。

方法

  • 匹配下一处
    boolean  find()
  • 重置匹配器,从start开始匹配下一处
    boolean  find(int start)
  • 获取先前已经匹配的字符串
    String  group()
  • 获取匹配成功的次数
    int  groupCount()
  • 从区域开头开始匹配
    boolean  lookingAt()
  • 整个区域进行匹配
    boolean  matches()
  • 获取该匹配器的正则表达式对象
    Pattern  pattern()
  • 对匹配器的区域进行限制
    Matcher  region(int start, int end)
  • 全部替换
    String  replaceAll(String replacement)
  • 替换匹配第一处
    String  replaceFirst(String replacement)
  • 重置匹配器
    Matcher  reset()
  • 使用新的字符序列重置匹配器
    Matcher  reset(CharSequence input)
  • 获取上一次匹配的开始索引
    int  start()

3. 匹配步骤

  • 将正则表达式的字符串格式先通过Pattern中的compile方法编译成Pattern正则表达式对象。
    Pattern p = Pattern.compile("a*b");
  • 要想用这个规则对字符串进行操作,还需要通过正则对象matcher方法和指定的字符串关联,并获取匹配器对象Matcher。
    Matcher m = p.matcher("aaaaab");
  • 用匹配器对象Matcher的功能(方法)对字符串进行操作。
    一般使用matches(),find(),lookingAt(),start(),end(),等方法。

4. 示例

    
    
package regex;
 
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class PatternDemo {
 
public static void main(String[] args) {
 
// 需求:获取字符串中由10个字母及以上组成的单词。
 
String str =
"Backslashes within string literals in Java source code are interpreted as required "
+ "by The Java Language Specification as either Unicode escapes (section 3.3) or other "
+ "character escapes (section 3.10.6) It is therefore necessary to double backslashes "
+ "in string literals that represent regular expressions to protect them from "
+ "interpretation by the Java bytecode compiler. The string literal b, "
+ "for example, matches a single backspace character when interpreted as a regular "
+ "expression, while b matches a word boundary. The string literal (hello) is illegal "
+ "and leads to a compile-time error; in order to match the string (hello) the string "
+ "literal (hello) must be used.";
 
// 定义规则。
String regex = "\\b[a-zA-Z]{10,}\\b";
 
// 1. 将正则字符串编译成正则对象。
Pattern p = Pattern.compile(regex );
 
// 2. 将正则对象和字符串相关联,并获取匹配器。
Matcher m = p.matcher(str);
 
// 3. 使用find的方法
/*
* m.lookingAt()方法从头匹配正则表达式一次。
* m.start()和m.end()分别能够获取匹配字符串的头尾索引值。
*/
while ( m.find()) {
System.out.println( m.group());
}
}
}

案例

1. 常见匹配

    
    
package regex;
 
import java.util.Arrays;
 
public class Text_Regex {
 
public static void main(String[] args) {
// 需求1:匹配电子邮箱
matchEmail();
 
/*
* 需求2:
* 把“我我.....我我.我....我.要.要要.....要.要学....学...学学....学.学编..编....编..编.编.程程.程...
* ..程.程程”
* 还原成:我要学编程。
*/
replace();
 
/*
* 需求3:
* 127.0.0.1 3.3.3.3 192.168.104.23 10.10.10.10
* 要求按照 ip地址的分类进行从小到大的排序。
*/
sortIP();
}
 
public static void sortIP() {
/*
* 思路:
* 由于需要按照数字排序,而字符串排序方式为字典顺序排序,所以先补零以获得同等长度IP地址字符串,再排序,最后还原。
*/
String ip = "127.0.0.1 3.3.3.3 192.168.104.23 10.10.10.10";
ip = ip.replaceAll( "(\\d+)", "00$1" );
ip = ip.replaceAll( "0*(\\d{3})", "$1" );
String[] ips = ip.split("\\s+");
Arrays.sort(ips );
for (String string : ips) {
string = string.replaceAll( "0*(\\d+)", "$1" );
System.out.println( string);
}
}
 
public static void replace() {
String str = "我我.....我我.我....我.要.要要.....要.要学....学...学学....学.学编..编....编..编.编.程程.程.....程.程程" ;
str = str.replaceAll( "\\.+", "" );
str = str.replaceAll( "(.)\\1+", "$1" );
System.out.println( str);
}
 
public static void matchEmail() {
String email = "jacobvv@163.com";
String regex = "\\w+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}" ;
boolean b = email.matches( regex);
System.out.println( b);
}
}

2. 网络爬虫

    
    
package regex;
 
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
 
public class Text_NetSpider {
 
public static void main(String[] args) {
/*
* 需求:网络爬虫
* 获取某网页上的所有邮箱地址
*/
String url = "http://tieba.baidu.com/p/2720132008";
Set<String> email = null;
try {
email = getEmail(url );
} catch (IOException e) {
e.printStackTrace();
}
for (String string : email) {
System.out.println( string);
}
}
 
public static Set<String> getEmail(String urlStr ) throws IOException {
Set<String> email = new HashSet<String>();
String regex = "\\w+@[a-zA-Z0-9]+(\\.[a-zA-Z]+){1,3}" ;
Pattern p = Pattern.compile(regex );
URL url = new URL( urlStr);
URLConnection conn = url.openConnection();
BufferedReader br = new BufferedReader( new InputStreamReader(conn.getInputStream()));
String content = null;
while (( content = br.readLine()) != null) {
Matcher m = p.matcher(content);
while ( m.find()) {
email.add( m.group());
}
}
br.close();
return email;
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值