在编程中,我们经常遇到字符串的各种处理问题:如在字符串中找出某个子字符串,亦或者字符串是否匹配某种规则。大量繁琐的规则判断令人焦头烂额,而正则表达式(Regular Expression)正是解决此类问题的一种功能强大的武器。这篇文章介绍了正则表达式的定义、匹配规则以及在java和python中的使用。
I. 定义
正则表达式是好用字符串描述的一种匹配规则,使用正则表达式可以快速判定给定的字符串是否符合匹配规则,除此之外还可以从字符串中搜索、提取、替换等符合规则的子字符串。
举例来说,当我们想要判断一串字符串数字是否符合电话号码的数字规则时(3位区号-8位数字,如027-12345678),可以使用正则表达式:”\d{3}-\d{8}“来进行判断。
II. 匹配规则
正则表达式的匹配规则是从左向右按规则匹配,常用的匹配规则如下:
III. 在编程语言中的使用
a. Java中的使用
在java标准库java.util.regex内建了正则表达式引擎。下面我来给大家一一讲述正则表达式不同功能在java中的实现。
1. 规则匹配
String.matches(regex)
函数可以直接判断当前String是否符合input中正则表达式的规则。
例子:
public class Main {
public static void main(String[] args){
String re = "java|python"; //正则表达式
System.out.println("java".matches(re)); //true
System.out.println("python".matches(re)); //true
System.ou..println("C++".matches(re)); //false
}
}
2. 分组匹配
我们可以用(...)
来讲正则表达式划分为不同的子规则,而每个子规则就是一个分组。如果我们想提取一串字符串中符合某个子分组规则的子字符串时,可以使用分组匹配。下面我用一个例子来详细讲解分组匹配的使用方法:
import java.util.regex.*;
public class Main {
public static void main(String[] args){
Pattern pattern = Pattern.compile("(\\d{3})\\-(\\d{8})");
Matcher matcher = pattern.matcher("027-12345678");
if (matcher.matches()) { //判断是否匹配
String whole = matcher.group(0); //提取整个String:"027-12345678"
String group1 = matcher.group(1); //提取符合第一组子规则的SubString:"027"
String group2 = matcher.group(2); //提取符合第二组子规则的SubString:"12345678"
} else{
System.out.println("Matching failed.")
}
}
}
Note:在java的字符串中,”\“需要用”\\“来表示。
在这个例子中,我们首先创建了Pattern对象pattern并用Pattern.compile(regex)
创建了正则表达式。然后我们创建一个Matcher对象matcher,并调用pattern.matcher(String string)
用来输入需要进行判断的字符串。接着我们用Matcher对象的matches( )
函数来判断字符串是否匹配规则,如果匹配成功就使用Matcher对象的group(int num)
方法来提取子字符串。
3. 非贪婪匹配
当我们使用分组匹配时,会遇到这样的问题:当我们想把数字“987000”分为“987”和“000”两组时,很容易的就想到了正则表达式:”(\d+)(0*)“并进行分组提取。但是这样得到的最终结果是group1 = “987000”, group2 = ““。因为”000”也是数字,而第一组规则匹配时进行了贪婪匹配。当我们想要使用非贪婪匹配的时候需要用到关键字”?“。所以,我们应该使用的正则表达式为:”(\d+?)(0*)“。例子如下:
import java.util.regex.*;
public class Main {
public static void main(String[] args){
Pattern pattern = Pattern.compile("(\\d+)(0*)");
Pattern pattern2 = Pattern.compile("(\\d+?)(0*)");
Matcher matcher = pattern.matcher("987000");
Matcher matcher2 = pattern2.matcher("987000");
if (matcher.matches()) { //判断是否匹配
String group1 = matcher.group(1); //提取符合第一组子规则的SubString:"987000"
String group2 = matcher.group(2); //提取符合第二组子规则的SubString:""
}
if (matcher2.matches()) { //判断是否匹配
String group1 = matcher2.group(1); //提取符合第一组子规则的SubString:"987"
String group2 = matcher2.group(2); //提取符合第二组子规则的SubString:"000"
}
}
}
Note:当出现??
(如d??
)时,前后两个?
意义不同。前一个?代表字符可以出现1次或0次,后一个字符代表非贪婪匹配。
4.分割字符串
String.split(regex)
方法可以用输入的正则表达式分割字符串。例子如下:
"a b c".split("\\s"); // { "a", "b", "c" }
"a b c".split("\\s"); // { "a", "b", "", "c" }
"a, b ;; c".split("[\\,\\;\\s]+"); // { "a", "b", "c" }
5. 搜索字符串
Matcher对象的find( )
方法可以搜索字符串,并用此对象的start( )
和end( )
方法提取它。例子如下:
public class Main {
public static void main(String[] args) {
String s = "the quick brown fox jumps over the lazy dog.";
Pattern p = Pattern.compile("\\wo\\w"); //两个字母中有o的情况
Matcher m = p.matcher(s);
while (m.find()) {
String sub = s.substring(m.start(), m.end());
System.out.println(sub); //row, fox, dog
}
}
}
6. 替换字符串
String.replaceAll(regex, string)
方法可以用正则表达式找到匹配规则的子字符串并用新的string来替换。例子如下:
public class Main {
public static void main(String[] args) {
String s = "The quick\t\t brown fox jumps over the lazy dog.";
String r = s.replaceAll("\\s+", " ");
System.out.println(r); // "The quick brown fox jumps over the lazy dog."
}
}
6.1 反向引用
可以使用$1
, $2
(数字代表是第几组)在替换字符串时进行反向引用。例如,当我们想在找到的字符串前后加上<b>xxxx<\b>可以使用如下代码:
public class Main {
public static void main(String[] args) {
String s = "the quick brown fox jumps over the lazy dog.";
String r = s.replaceAll("\\s([a-z]{4})\\s", " <b>$1</b> ");
System.out.println(r); //the <b>k</b> brown fox <b>s</b> over the lazy dogs.
}
}
b. Python中的使用
Python提供了re模块,其中包含了所有正则表达式的功能。由于python字符串本身也用”\“转义,所以在使用正则表达式时最好使用python的r
前缀,这样就不用考虑转义的问题了。
1. 规则匹配
match()
方法判断是否匹配,如果匹配成功,返回一个Match
对象,否则返回None
。常见的判断方法就是:
import re
test = '用户输入的字符串'
if re.match(r'正则表达式', test):
print('ok')
else:
print('failed')
2. 分组匹配
python和java一样,在正则表达式中使用(...)
来进行分组,在分组中依旧是使用group()
方法。例子如下:
m = re.match(r'^(\d{3})-(\d{8})$', '027-12345678')
m.group(0) #提取整个字符串:'027-12345678'
m.group(1) #提取第一组子字符串:'027'
m.group(2) #提取第二组子字符串:'12345678'
3. 非贪婪匹配
python和java一样,默认是贪婪匹配。需要非贪婪匹配时依旧是使用关键字?
,例子如下:
re.match(r'^(\d+)(0*)$', '987000').groups() #('987000', '')
re.match(r'^(\d+?)(0*)$', '987000').groups() #('987', '000')
4. 分割字符串
re.spit(regex, string)
函数用来分割字符串。例子如下:
re.split(r'\s+', 'a b c') #['a', 'b', 'c']
re.split(r'[\s\,]+', 'a,b, c d') #['a', 'b', 'c', 'd']
5. 搜索字符串
re.search(regex, string)
函数用来查找第一个符合正则表达式规则的String。例子如下:
import re
m = re.search(r'def', 'abcdef')
m.group(0) #def
m.span() #(3,5)
6. 替换字符串
re.sub(regex, string)
用来替换字符串,并返回新的字符串。如果没找到则返回原字符串。例子如下:
import re
text = 'how are you'
print re.sub('\s+', '-', text) #how-are-you
IV. 总结
正则表达式是一种功能强大的字符串匹配规则。我们可以使用它对字符串进行匹配、分组匹配与提取、查找、分割、替换等操作。
V. 参考
https://www.liaoxuefeng.com/wiki/1252599548343744/1255945288020320
Share this post
Twitter
Google+
Facebook
Reddit
LinkedIn
StumbleUpon
Pinterest
Email