正则表达式入门以及参考手册:https://deerchao.cn/tutorials/regex/regex.htm#grouping
反斜杠与转义字符
在其他语言中,转义字符是 \ ,反斜杠是 \\ 。
在 Java 中,转义字符是 \\ ,反斜杠是 \\\\ 。
所以,在其他的语言中,一个反斜杠 \ 就足以具有转义的作用,而在 Java 中正则表达式中则需要有两个反斜杠才能被解析为其他语言中的转义作用。也可以简单的理解在 Java 的正则表达式中,两个 \ 代表其他语言中的一个 \,这也就是为什么表示一位数字的正则表达式是 \\d,而表示一个普通的反斜杠是 \\\\ 。
Java String类与正则表达式有关的方法
- boolean matches(String regex) 判断字符串是否全部正则匹配
- String replaceAll(String regex, String replacement) 使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。
- String replaceFirst(String regex, String replacement) 使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
- String[] split(String regex) 根据给定正则表达式的匹配拆分此字符串。
- String[] split(String regex, int limit) 根据给定正则表达式的匹配拆分此字符串,并给出最大份数,达到最大份数后不再进行分割。
除此之外的其他用法则需要用到java.util.regex 包下的三个类:
- Pattern 类:
Pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个 Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个 Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。- Matcher 类:
Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用 Pattern 对象的 matcher 方法来获得一个 Matcher 对象。- PatternSyntaxException异常类:
表示一个正则表达式模式中的语法错误。
下面的Java代码:
public static void main(String[] args) {
String regex = "\\{([^}])*\\}";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher("ab{gnfnm}ah{hell}o");
while (matcher.find()) {
System.out.println(matcher.group());
}
}
输出:
{gnfnm}
{hell}
分析:\\ { ( [ ^ } ] * ) \\ }
\{ 表示匹配 {,{是元字符,要用\转义。
()用来指定子表达式。如果是单个字符比如匹配0个或多个A,要用A*,如果这里A也是一个表达式的话要用()括起来,后面再加限定符。
[]中可以直接列出要匹配的字符或数字,[aeiou]匹配元音字母,[0-9]匹配0到9,作用同\d。
^}表示匹配 } 以外的字符。
例题:LeetCode 394 字符串解码
这里是给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。引用
示例 1:
输入:s = “3[a]2[bc]”
输出:“aaabcbc”
示例 2:
输入:s = “3[a2[c]]”
输出:“accaccacc”
示例 3:
输入:s = “2[abc]3[cd]ef”
输出:“abcabccdcdcdef”
示例 4:
输入:s = “abc3[cd]xyz”
输出:“abccdcdcdxyz”
提示:
1 <= s.length <= 30
s 由小写英文字母、数字和方括号 ‘[]’ 组成
s 保证是一个 有效 的输入。
s 中所有整数的取值范围为 [1, 300]
代码:
import java.util.regex.*;
class Solution {
public String decodeString(String s) {
String regex = "\\d+\\[([\\w])*\\]";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(s);
String str=s;
if (matcher.find()) {
String s3=translate(matcher.group());
str=str.replaceFirst(regex,s3);
} else return str;
return decodeString(str);
}
public String translate(String s){
String[] ss=s.split("\\[");
String s2=ss[1].substring(0,ss[1].length()-1);
String s3="";
for(int r=Integer.parseInt(ss[0]);r>0;r--){
s3+=s2;
}
return s3;
}
}
分析:\\d+\\[([\\w])*\\]
表示匹配任意数、中括号并且里面是单词,如21[acb]这种格式。每次只按这种模式匹配一次,然后解析替换,再进入下一个递归逻辑中进行匹配。等再匹配不到这种模式了,就结束递归,得出结果。
如2[ab3[cd]]4[xy],第一次递归中3[cd]会被先捕获到,然后转化成2[abcdcdcd]4[xy]进入到下一步。
第二次递归中2[abcdcdcd]4[xy]会捕获到2[abcdcdcd],将其转化成abcdcdcdabcdcdcd4[xy]再进入到下一步。
最后一次递归则会得出abcdcdcdabcdcdcdxyxyxyxy。