java - 字符类中的元字符 (`[]`)
问题描述
我对 Java Regex 的理解是这样的。有两组元字符:
- 在字符类之外的正则表达式中使用(包含在 内
[]
):<([{\\^-=$!|]})?*+.>
- 在字符类中使用:
\][-&^
如果我们希望某个字符(例如连字符-
)在字符类中按字面意思匹配,我们必须用反斜杠 ( \
) 对其进行转义。
Java Doc中的以下描述支持此视图
字符类 字符类可能出现在其他字符类中,并且可能由联合运算符(隐式)和交集运算符(&&)组成。联合运算符表示一个类,该类包含至少一个操作数类中的每个字符。交集运算符表示一个类,该类包含其两个操作数类中的每个字符。
字符类运算符的优先级如下,从高到低:
- 文字转义 \x
- 分组 [...]
- 范围
- 联合 [ae][iu]
- 交点 [az&&[aeiou]]
请注意,字符类内部的元字符集与字符类外部的元字符集不同。
这是一个正确的理解吗?
令我吃惊的是,要转义字符类中的第二组,除了使用反斜杠之外,我们似乎还可以使用java.util.regex.Pattern.quote()
. 我认为该方法仅适用于第一组元字符。
测试程序
以下测试程序说明Pattern.quote()
and \
(以及\Q
and \E
)都可用于在字符类中引用连字符:
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import java.util.regex.Pattern;
public class RegexTest {
@Rule
public TestName testName = new TestName();
@Test
public void testHyphenCharClassByPatternQuote() {
String regex = "[" + Pattern.quote("-") + "]";
Pattern p = Pattern.compile(regex);
String[] tests = {
"-"
, "a"
};
for (String test : tests) {
System.out.println(testName.getMethodName() + " matching " + test + ":" + p.matcher(test).matches());
}
}
@Test
public void testHyphenCharClassByBackSlash() {
String regex = "[\\-]";
Pattern p = Pattern.compile(regex);
String[] tests = {
"-"
, "a"
};
for (String test : tests) {
System.out.println(testName.getMethodName() + " matching " + test + ":" + p.matcher(test).matches());
}
}
@Test
public void testHyphenCharClassByQE() {
String regex = "[\\Q-\\E]";
Pattern p = Pattern.compile(regex);
String[] tests = {
"-"
, "a"
};
for (String test : tests) {
System.out.println(testName.getMethodName() + " matching " + test + ":" + p.matcher(test).matches());
}
}
}
测试输出
testHyphenCharClassByQE matching -:true
testHyphenCharClassByQE matching a:false
testHyphenCharClassByBackSlash matching -:true
testHyphenCharClassByBackSlash matching a:false
testHyphenCharClassByPatternQuote matching -:true
testHyphenCharClassByPatternQuote matching a:false
解决方案
您基本上是正确的,但是该pattern.quote()
方法按预期工作。似乎让您感到困惑的是字符类别范围内连字符的性质。
Pattern 类文档在引用 部分下列出了以下转义修饰符:
\
无,但引用以下字符
\Q
无,但引用所有字符,直到\E
\E
无,但结束引用开始于\Q
pattern.quote
所做的就是用文字包装输入并\Q
生成\E
文字字符串。
引用 Java 文档quote
返回指定字符串的文字模式字符串。此方法生成一个字符串,可用于创建一个模式,该模式将匹配字符串 s,就好像它是文字模式一样。
输入序列中的元字符或转义序列将没有特殊含义。
从技术上讲,从 a \Q
(exclusive) 到 next \E
(exclusive) 的所有内容,可能包括任意数量的\Q
序列,都是字面化的。
当您在字符类中转义/引用连字符(或将其放在末尾)时,它将失去其特殊含义,即定义一个范围,并且它只是变成一个文字连字符,如您自己所证明的:
String regex = "[a\\-z]";
Pattern p = Pattern.compile(regex);
String[] tests = {
"-"
, "a"
, "b"
, "z"
};
for (String test : tests) {
System.out.println(" matching " + test + ":" + p.matcher(test).matches());
}
输出:
matching -:true
matching a:true
matching b:false
matching z:true
推荐阅读
- mysql - 如何计算当前订单之前的订单数量
- c# - 如何解决从 UWP 应用程序读取文件时 Permission denied 的问题?
- java - 让 Thymeleaf 读取对象模型数组
- amazon-web-services - CloudWatch 日志定价混乱
- python - 运行 npm install 时,使用 pxssh 建立的 ssh 连接会中断。为什么?
- c# - 在用于连接两个表的 SQL 查询中插入值
- excel - 当后续行中的单元格填写完成任务的人的ID时,如何在开始时间旁边的单元格中输入任务的“结束时间”?
- android - 无法为 org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler 类型的对象设置未知属性“实现”
- javascript - Puppeteer:让浏览器看起来不像机器人/脚本
- python - 如何仅从python中的字符串中获取整数部分?