java.util.regex.Pattern类使用

本文详细介绍了Java中Pattern类的使用方法,包括正则表达式的构造、转义字符、字符类、行结束符处理等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java.util.regex.Pattern类使用

标签: 正则表达式perljavagraphcharacter嵌入式
6136人阅读 评论(2) 收藏 举报
本文章已收录于:
   
public final class Pattern extends Object implements Serializable
 

正则表达式的编译表示形式。

指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建 Matcher 对象,依照正则表达式,该对象可以与任意字符序列匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式。

因此,典型的调用顺序是

Pattern p = Pattern.compile("a*b");
 Matcher m = p.matcher("aaaaab");
 boolean b = m.matches();

在仅使用一次正则表达式时,可以方便地通过此类定义 matches 方法。此方法编译表达式并在单个调用中将输入序列与其匹配。语句

boolean b = Pattern.matches("a*b", "aaaaab");
等效于上面的三个语句,尽管对于重复的匹配而言它效率不高,因为它不允许重用已编译的模式。

此类的实例是不可变的,可供多个并发线程安全使用。Matcher 类的实例用于此目的则不安全。 非捕获组

正则表达式的构造摘要
构造匹配
 
字符
x字符 x
\\反斜线字符
\0n带有八进制值 0 的字符 n (0 <= n <= 7)
\0nn带有八进制值 0 的字符 nn (0 <= n <= 7)
\0mnn带有八进制值 0 的字符 mnn(0 <= m <= 3、0 <= n <= 7)
\xhh带有十六进制值 0x 的字符 hh
\uhhhh带有十六进制值 0x 的字符 hhhh
\t制表符 ('\u0009')
\n新行(换行)符 ('\u000A')
\r回车符 ('\u000D')
\f换页符 ('\u000C')
\a报警 (bell) 符 ('\u0007')
\e转义符 ('\u001B')
\cx对应于 x 的控制符
 
字符类
[abc]ab 或 c(简单类)
[^abc]任何字符,除了 ab 或 c(否定)
[a-zA-Z]a 到 z 或 A 到 Z,两头的字母包括在内(范围)
[a-d[m-p]]a 到 d 或 m 到 p[a-dm-p](并集)
[a-z&&[def]]de 或 f(交集)
[a-z&&[^bc]]a 到 z,除了 b 和 c[ad-z](减去)
[a-z&&[^m-p]]a 到 z,而非 m 到 p[a-lq-z](减去)
 
预定义字符类
.任何字符(与行结束符可能匹配也可能不匹配)
\d数字:[0-9]
\D非数字: [^0-9]
\s空白字符:[ \t\n\x0B\f\r]
\S非空白字符:[^\s]
\w单词字符:[a-zA-Z_0-9]
\W非单词字符:[^\w]
 
POSIX 字符类(仅 US-ASCII)
\p{Lower}小写字母字符:[a-z]
\p{Upper}大写字母字符:[A-Z]
\p{ASCII}所有 ASCII:[\x00-\x7F]
\p{Alpha}字母字符:[\p{Lower}\p{Upper}]
\p{Digit}十进制数字:[0-9]
\p{Alnum}字母数字字符:[\p{Alpha}\p{Digit}]
\p{Punct}标点符号:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
\p{Graph}可见字符:[\p{Alnum}\p{Punct}]
\p{Print}可打印字符:[\p{Graph}\x20]
\p{Blank}空格或制表符:[ \t]
\p{Cntrl}控制字符:[\x00-\x1F\x7F]
\p{XDigit}十六进制数字:[0-9a-fA-F]
\p{Space}空白字符:[ \t\n\x0B\f\r]
 
java.lang.Character 类(简单的 java 字符类型
\p{javaLowerCase}等效于 java.lang.Character.isLowerCase()
\p{javaUpperCase}等效于 java.lang.Character.isUpperCase()
\p{javaWhitespace}等效于 java.lang.Character.isWhitespace()
\p{javaMirrored}等效于 java.lang.Character.isMirrored()
 
Unicode 块和类别的类
\p{InGreek}Greek 块(简单)中的字符
\p{Lu}大写字母(简单类别
\p{Sc}货币符号
\P{InGreek}所有字符,Greek 块中的除外(否定)
[\p{L}&&[^\p{Lu}]]所有字母,大写字母除外(减去)
 
边界匹配器
^行的开头
$行的结尾
\b单词边界
\B非单词边界
\A输入的开头
\G上一个匹配的结尾
\Z输入的结尾,仅用于最后的结束符(如果有的话)
\z输入的结尾
 
Greedy 数量词
X?X,一次或一次也没有
X*X,零次或多次
X+X,一次或多次
X{n}X,恰好 n 次
X{n,}X,至少 n 次
X{n,m}X,至少 n 次,但是不超过 m 次
 
Reluctant 数量词
X??X,一次或一次也没有
X*?X,零次或多次
X+?X,一次或多次
X{n}?X,恰好 n 次
X{n,}?X,至少 n 次
X{n,m}?X,至少 n 次,但是不超过 m 次
 
Possessive 数量词
X?+X,一次或一次也没有
X*+X,零次或多次
X++X,一次或多次
X{n}+X,恰好 n 次
X{n,}+X,至少 n 次
X{n,m}+X,至少 n 次,但是不超过 m 次
 
Logical 运算符
XYX 后跟 Y
X|YX 或 Y
(X)X,作为捕获组
 
Back 引用
\n任何匹配的 nth 捕获组
 
引用
\Nothing,但是引用以下字符
\QNothing,但是引用所有字符,直到 \E
\ENothing,但是结束从 \Q 开始的引用
 
特殊构造(非捕获)
(?:X)X,作为非捕获组
(?idmsux-idmsux)Nothing,但是将匹配标志i d m s u x on - off
(?idmsux-idmsux:X)  X,作为带有给定标志 i d m s u x on - off
(?=X)X,通过零宽度的正 lookahead
(?!X)X,通过零宽度的负 lookahead
(?<=X)X,通过零宽度的正 lookbehind
(?<!X)X,通过零宽度的负 lookbehind
(?>X)X,作为独立的非捕获组

反斜线、转义和引用

反斜线字符 ('\') 用于引用转义构造,如上表所定义的,同时还用于引用其他将被解释为非转义构造的字符。因此,表达式 \\ 与单个反斜线匹配,而 \{ 与左括号匹配。

在不表示转义构造的任何字母字符前使用反斜线都是错误的;它们是为将来扩展正则表达式语言保留的。可以在非字母字符前使用反斜线,不管该字符是否非转义构造的一部分。

根据

字符类

字符类可以出现在其他字符类中,并且可以包含并集运算符(隐式)和交集运算符 (&&)。并集运算符表示至少包含其某个操作数类中所有字符的类。交集运算符表示包含同时位于其两个操作数类中所有字符的类。

字符类运算符的优先级如下所示,按从最高到最低的顺序排列:

1    字面值转义    \x
2    分组[...]
3    范围a-z
4    并集[a-e][i-u]
5    交集[a-z&&[aeiou]]

注意,元字符的不同集合实际上位于字符类的内部,而非字符类的外部。例如,正则表达式 . 在字符类内部就失去了其特殊意义,而表达式 - 变成了形成元字符的范围。

行结束符

行结束符 是一个或两个字符的序列,标记输入字符序列的行结尾。以下代码被识别为行结束符:

  • 新行(换行)符 ('\n')、
  • 后面紧跟新行符的回车符 ("\r\n")、
  • 单独的回车符 ('\r')、
  • 下一行字符 ('\u0085')、
  • 行分隔符 ('\u2028') 或
  • 段落分隔符 ('\u2029)。

如果激活

如果未指定

默认情况下,正则表达式 ^$ 忽略行结束符,仅分别与整个输入序列的开头和结尾匹配。如果激活 MULTILINE 模式,则 ^ 在输入的开头和行结束符之后(输入的结尾)才发生匹配。处于 MULTILINE 模式中时,$ 仅在行结束符之前或输入序列的结尾处匹配。 Unicode Technical Standard #18:Unicode Regular Expression Guidelines 第 1 级和 RL2.1 Canonical Equivalents。

组和捕获

捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:

1    ((A)(B(C)))
2    \A
3    (B(C))
4    (C)

组零始终代表整个表达式。

之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。捕获的子序列稍后可以通过 Back 引用在表达式中使用,也可以在匹配操作完成后从匹配器获取。

与组关联的捕获输入始终是与组最近匹配的子序列。如果由于量化的缘故再次计算了组,则在第二次计算失败时将保留其以前捕获的值(如果有的话)例如,将字符串 "aba" 与表达式 (a(b)?)+ 相匹配,会将第二组设置为 "b"。在每个匹配的开头,所有捕获的输入都会被丢弃。

(?) 开头的组是纯的非捕获 组,它不捕获文本,也不针对组合计进行计数。

Unicode 支持

此类符合

Java 源代码中的 Unicode 转义序列(如 \u2014)是按照 Java Language Specification 的 第 3.3 节中的描述处理的。这样的转义序列还可以由正则表达式解析器直接实现,以便在从文件或键盘击键读取的表达式中使用 Unicode 转义。因此,可以将不相等的字符串 "\u2014""\\u2014" 编译为相同的模式,从而与带有十六进制值 0x2014 的字符匹配。 Character 类指定版本中的 The Unicode Standard 的类别。类别名称是在 Standard 中定义的,即标准又丰富。Pattern 所支持的块名称是 UnicodeBlock.forName 所接受和定义的有效块名称。 上文所述。

与 Perl 中一样,Unicode 块和类别是使用 \p\P 构造编写的。如果输入具有属性 prop,则与 \p{prop} 匹配,而输入具有该属性时与 \P{prop} 不匹配。块使用前缀 In 指定,与在 InMongolian 中一样。可以使用可选前缀 Is 指定类别:\p{L}\p{IsL} 都表示 Unicode 字母的类别。块和类别在字符类的内部和外部都可以使用。

受支持的类别是由

行为类似 java.lang.Character boolean 是 methodname 方法(废弃的类别除外)的类别,可以通过相同的 \p{prop} 语法来提供,其中指定的属性具有名称 javamethodname

与 Perl 5 相比较

Pattern 引擎用有序替换项执行传统上基于 NFA 的匹配,与 Perl 5 中进行的相同。

此类不支持 Perl 构造:

  • 条件构造 (?{X})(?(condition)X|Y)

  • 嵌入式代码构造 (?{code})(??{code})

  • 嵌入式注释语法 (?#comment)

  • 预处理操作 \l \u\L\U

此类支持但 Perl 不支持的构造:

  • Possessive 数量词,它可以尽可能多地进行匹配,即使这样做导致所有匹配都成功时也如此。

  • 字符类并集和交集,如

Java Language Specification 的要求,Java 源代码的字符串中的反斜线被解释为 Unicode 转义或其他字符转义。因此必须在字符串字面值中使用两个反斜线,表示正则表达式受到保护,不被 Java 字节码编译器解释。例如,当解释为正则表达式时,字符串字面值 "\b" 与单个退格字符匹配,而 "\\b" 与单词边界匹配。字符串字面值 "\(hello\)" 是非法的,将导致编译时错误;要与字符串 (hello) 匹配,必须使用字符串字面值 "\\(hello\\)"UNIX_LINES 模式,则新行符是唯一识别的行结束符。 DOTALL 标志,则正则表达式 . 可以与任何字符(行结束符除外)匹配。

2
0
 
 
<think>我们正在处理一个正则表达式错误:`PatternSyntaxException: Illegal repetition near index 1`,并且错误的正则表达式是`^.{GCBH}`。 错误原因分析: 1. 在正则表达式中,`{`和`}`用于指定重复次数,例如`a{3}`表示匹配3个a。但是,在`^.{GCBH}`中,`{GCBH}`不是合法的重复语法,因为花括号内的内容必须是数字或者数字范围(如`{3}`, `{3,5}`),或者是某些特定的模式(如`{n}`, `{n,}`, `{n,m}`)。这里出现了字母,所以会抛出非法重复(Illegal repetition)的异常。 2. 用户意图可能是:用变量`GCBH`的值(即字符串"S186701S")作为要匹配的前缀,然后替换掉。但是,在正则表达式中,我们无法直接将一个变量放入模式中,除非我们进行字符串拼接。而且,这里用户还使用了`^.{GCBH}`,这显然不是正确的用法。 3. 实际上,用户可能想要删除字符串`TH`中开头部分等于`GCBH`字符串的内容。注意,`GCBH`的值是"S186701S",而`TH`的值是"S186701S-T0101",所以用户可能想删除开头的"S186701S",得到"-T0101"。 但是,当前的正则表达式写法是完全错误的。 解决方案: 我们应该使用正确的正则表达式,并且注意,如果我们要匹配一个固定的字符串(即字面量),我们应该使用`Pattern.quote`来转义任何可能被解释为正则元字符的字符。但是,这里我们不需要使用量词,而是直接匹配整个字符串。 因此,我们可以这样写: ```java String GCBH = "S186701S"; String TH = "S186701S-T0101"; // 我们想要删除开头的GCBH字符串,注意:如果TH不是以GCBH开头,则不会替换 String X = TH.replaceFirst("^" + Pattern.quote(GCBH), ""); ``` 解释: - `replaceFirst`用于替换第一个匹配项(因为我们只需要匹配开头)。 - `^`表示字符串的开头。 - `Pattern.quote(GCBH)`将字符串`GCBH`中的特殊字符转义,使其作为字面量处理。例如,如果`GCBH`中包含点(.)或星号(*)等,它们不会被解释为正则元字符。 但是,注意:在原始代码中,用户使用了`replaceAll`,但我们这里使用`replaceFirst`,因为只需要匹配一次(在开头)。当然,也可以使用`replaceAll`,但需要确保只匹配开头一次,所以`replaceFirst`更合适。 如果用户确实想用正则表达式,并且`GCBH`字符串中不包含正则特殊字符,也可以直接拼接: ```java String X = TH.replaceFirst("^" + GCBH, ""); ``` 但是,为了安全起见,使用`Pattern.quote`是更好的做法。 另外,如果用户不想使用正则表达式,也可以使用字符串操作: ```java if (TH.startsWith(GCBH)) { String X = TH.substring(GCBH.length()); } else { String X = TH; } ``` 这样更直接,且没有正则表达式的复杂性和潜在错误。 根据用户提供的错误信息,我们得知错误是因为在正则表达式中使用了非法重复(`{GCBH}`)。因此,修正的核心是避免这种非法的正则语法。 引用[1]和[3]都提到了`Illegal repetition`,这通常是因为在量词`{}`中使用了非数字的内容。而引用[2]则是一个Unicode属性错误,与本问题无关。 因此,我们给出两种解决方案: 1. 使用正则表达式(但正确拼接)并转义字面量。 2. 使用字符串操作(substring)。 推荐使用第二种,因为意图是删除固定前缀,使用字符串操作更简单高效。 代码示例: ```java String GCBH = "S186701S"; String TH = "S186701S-T0101"; String X; if (TH.startsWith(GCBH)) { X = TH.substring(GCBH.length()); } else { X = TH; // 如果不是以GCBH开头,则保持不变 } System.out.println(X); // 输出: -T0101 ``` 这样就不会出现正则表达式错误了。 相关问题: 1.Java中如何安全地使用字符串作为正则表达式模式? 2. 处理字符串前缀时,使用正则表达式和字符串操作哪个更好? 3. 如何避免`PatternSyntaxException`异常? 4. 在字符串替换中,`replace`、`replaceAll`和`replaceFirst`有什么区别?</think>针对 Java 正则表达式 `^.{GCBH}` 导致的 `PatternSyntaxException: Illegal repetition near index 1` 错误,以下是详细解决方案: ### 错误原因分析 1. **非法重复语法**: ```java TH.replaceAll("^.{GCBH}", ""); // 错误! ``` - `{GCBH}` 是非法正则量词,量词必须为数字格式(如 `{4}`)或范围(如 `{1,5}`) - Java 将 `{G` 视为非法重复语法触发异常[^1][^3] 2. **变量未正确引用**: - 意图可能是用变量 `GCBH` 的值("S186701S")作为匹配模式 - 但直接写入 `{GCBH}` 会被当作字面字符而非变量引用 --- ### 解决方案 #### 方案 1:正确使用变量(推荐) ```java String GCBH = "S186701S"; String TH = "S186701S-T0101"; // 转义特殊字符后拼接变量 String regex = "^" + Pattern.quote(GCBH); String X = TH.replaceFirst(regex, ""); System.out.println(X); // 输出: -T0101 ``` - **关键点**: - `Pattern.quote()` 转义变量中的正则特殊字符(如 `.` `*` 等)[^3] - 使用 `replaceFirst()` 替代 `replaceAll()` 更高效(只需匹配开头一次) #### 方案 2:固定长度匹配(若需通用前缀) ```java // 匹配开头9个字符(GCBH长度) String X = TH.replaceFirst("^.{9}", ""); ``` - 适用场景:当 `GCBH` 长度固定且无特殊字符时 #### 方案 3:非正则的字符串操作 ```java String X = TH.startsWith(GCBH) ? TH.substring(GCBH.length()) : TH; ``` - **优势**:完全避免正则,性能更高 - **输出**:`-T0101` --- ### 错误预防指南 | **错误写法** | **修复方案** | **原理** | |---------------------|----------------------------------|------------------------------| | `^.{GCBH}` | `^ + Pattern.quote(GCBH)` | 转义特殊字符并正确拼接变量 | | `{ABC}` | 改为数字量词如 `{3}` | 量词必须为数字 | | 未处理边界符 `^` | 添加 `(?m)` 启用多行模式 | 确保 `^` 匹配每行开头 | | 未处理元字符 `.` | 用 `\\.` 转义 | `.` 在正则中表示任意字符 | > **最佳实践**: > 使用 [Regex Tester](https://regex101.com/) 在线测试正则表达式,或添加异常处理: > ```java > try { > TH.replaceAll(regex, ""); > } catch (PatternSyntaxException e) { > System.err.println("正则错误: " + e.getMessage()); > } > ``` --- ### 根本问题解析 `Illegal repetition` 异常通常由以下原因触发: 1. **量词格式错误**:`{x}` 中 `x` 必须为整数 ```java // 错误示例:字母代替数字 "a{xyz}".matches("a{xyz}"); // 抛出 PatternSyntaxException[^1][^3] ``` 2. **特殊字符未转义**:如 `{` `}` `.` `*` 等未用反斜杠转义 ```java // 正确转义示例 "price: $5.99".replaceAll("\\$", "¥"); // 输出: price: ¥5.99 ``` 3. **Unicode 属性错误**:`\p{...}` 包含无效属性名时触发 `Incorrect Unicode property`[^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值