【Java】Java正则表达式匹配
一、正则表达式匹配
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexExtract {
public static boolean isEmpty(final CharSequence cs) {
return cs == null || cs.length() == 0;
}
private static String getRegexValue(String input, String regex, int group) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
return matcher.group(group);
}
return "";
}
public static String getTableNameFromCreateTableSql(String sql) throws IOException {
String checkResult = "";
// 匹配出 schema.表名
// String regex = "create\\s*table\\s*(if\\s*not\\s*exists\\s*)?(.*)(\\s\\()";
// String exceptionTableName = getRegexValue(sql.toLowerCase(), regex, 2);
// 匹配出 表名
String regex = "create\\s*table\\s*(if\\s*not\\s*exists\\s*)?(.*\\.)?(.*)(\\s\\()";
String exceptionTableName = getRegexValue(sql.toLowerCase(), regex, 3);
if (!isEmpty(exceptionTableName))
checkResult = exceptionTableName;
return checkResult;
// return exceptionTableName;
}
public static String getTableNameFromCreateTableSql2(String sql) throws IOException {
String tableName = "";
String regex = "create\\s*table\\s*(if\\s*not\\s*exists\\s*)?(.*\\.)?(.*)(\\s\\()";
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(sql);
if (matcher.find()) {
tableName = matcher.group(3); // 提取匹配的部分
} else {
tableName = "";
}
return tableName;
}
public static void main(String[] args) throws IOException {
String sql = "";
sql = "CREATE TABLE tzq_gd.tzq_log_t (";
String result = getTableNameFromCreateTableSql(sql);
System.out.println(result);
String result2 = getTableNameFromCreateTableSql2(sql);
System.out.println(result2);
}
}
二、正则表达式说明
2.1、\w
\w
在正则表达式中,\w
是一个元字符,用来匹配任何字母数字字符及下划线。具体来说,它等价于 [a-zA-Z0-9_]
,这意味着它可以匹配:
- 任何单个字母(大写或小写),即
a
到z
和A
到Z
- 任何单个数字,即
0
到9
- 下划线
_
例如,在字符串 “Hello123” 中,\w
可以匹配每一个字符 “H”、“e”、“l”、“l”、“o”、“1”、“2” 和 “3”。
2.2、*
*
在正则表达式中,星号 *
是一个量词,它表示其前一个字符(或字符组)可以出现任意次,包括0次。具体来说,如果在正则表达式中某个字符后面加上星号 *
,那么这个字符可以不出现,或者出现一次,或者多次。
例如:
a*
匹配任何包含零个或多个 ‘a’ 的字符串,如:""
(空字符串),"a"
,"aa"
,"aaa"
等。ba*n
匹配以 ‘b’ 开始,后跟零个或多个 ‘a’,最后是一个 ‘n’ 的字符串,如:"bn"
,"ban"
,"baan"
,"baaan"
等。
2.3、?
?
在正则表达式中,问号 ?
也是一个量词,它表示其前一个字符(或字符组)可以出现0次或1次。换句话说,问号 ?
使得前一个字符变为可选的。
具体来说:
a?
匹配包含零个或一个 ‘a’ 的字符串,如:""
(空字符串),"a"
。colou?r
匹配 “color” 和 “colour”。
举一些例子:
a?b
可以匹配"b"
和"ab"
。http://www\.example\.com/?(index\.html)?
可以匹配http://www.example.com/
和http://www.example.com/index.html
。
2.4、.
.
在正则表达式中,“.” 是一个特殊字符(元字符),它的意思是:
匹配除换行符
以外的任意单个字符。
举个例子来说明:
正则表达式:a.c
这个正则表达式表示:
- 匹配以
a
开头, - 中间有一个任意字符(但不能是换行符),
- 以
c
结尾 的三个字符的字符串。
匹配结果:
abc
✅a2c
✅a c
✅(中间是空格)ac
❌(因为只有两个字符,中间没有字符)a c
❌(中间是换行符,.
不匹配换行符)
补充说明:
- 如果你希望
.
能匹配包括换行符在内的所有字符,通常需要使用“单行模式”(也叫“点号匹配所有模式”),具体语法因语言而异。例如:- 在 Python 中使用
re.DOTALL
标志; - 在 JavaScript 中使用
s
修饰符(如/a.c/s
); - 在 Java 中使用
Pattern.DOTALL
。
- 在 Python 中使用
总结:
字符 | 含义 |
---|---|
. | 匹配任意一个字符(除换行符 ` |
` 以外) |
2.5、()
()
1. 单个括号 ()
的作用(分组)
括号 ()
在正则表达式中主要有以下几个用途:
a. 分组表达式
将多个字符或子表达式组合为一个整体,例如:
(ab)+
这个表达式匹配的是 ab
重复一次或多次,比如 ab
, abab
, ababab
等。
b. 捕获分组
括号可以捕获匹配的内容,并可以通过反向引用(如 \1
, \2
等)来引用这些内容。
例如:
(\d{3})-(\d{3}-\d{4})
这个正则可以匹配电话号码如 123-456-7890
,其中:
(\d{3})
捕获前三个数字;(\d{3}-\d{4})
捕获后面的数字部分;\1
和\2
可以引用这两个分组的内容。
2. “双括号” (())
的含义(即嵌套括号)
如果你看到的是 双括号 (())
,这表示的是嵌套的分组,比如:
((a)(b))
这个表达式匹配的是 ab
,并将其分为两个分组:
- 第一个括号
((a)(b))
是整个分组; - 第二个括号
(a)
是第一个分组内的子分组; - 第三个括号
(b)
也是第一个分组内的另一个子分组。
这种结构在反向引用中可能会用到,例如:
(\d{3})-(\d{3})-(\d{4})
可以写成嵌套形式:
((\d{3})-(\d{3}))-(\d{4})
3. 非捕获分组((?:...)
)
如果你只是想分组而不捕获内容(即不想保存匹配的内容),可以使用非捕获分组:
(?:abc)+
这个表达式匹配的是 abc
重复一次或多次,但不会保存每个匹配的内容。
总结
表达式 | 说明 |
---|---|
() | 捕获分组,同时分组和保存匹配内容 |
(()) | 嵌套分组,多个分组层级 |
(?:...) | 非捕获分组,仅分组不保存 |
如果你看到的是 ()
但不是嵌套的情况,那它就是普通的分组和捕获操作。