java - 如何使捕获组可选?
问题描述
输入
example("This is tes't")
example('This is the tes\"t')
输出应该是
This is tes't
This is the tes"t
代码
String text = "example(\"This is tes't\")";
//String text = "$.i18nMessage('This is the tes\"t\')";
final String quoteRegex = "example.*?(\".*?\")?('.*?')?";
Matcher matcher0 = Pattern.compile(quoteRegex).matcher(text);
while (matcher0.find()) {
System.out.println(matcher0.group(1));
System.out.println(matcher0.group(2));
}
我看到输出为
null
null
虽然当我使用正则表达式时example.*?(\".*?\")
它返回This is tes't
并且当我使用example.*?('.*?')
它时返回
This is the tes"t
但是当我将两者结合使用example.*?(\".*?\")?('.*?')?
它返回 null 。为什么 ?
解决方案
.*?(\".*?\")?('.*?')?
正则表达式末尾的子模式序列可以匹配一个空字符串(所有 3 个部分都用匹配0 个或更多字符的*
/量化)。*?
在匹配之后example
,.*?
首先跳过,并且仅在后续子模式不匹配时才扩展。但是,它们都匹配之前的空字符串(
,因此,您只有example
in matcher0.group(0)
。
使用使第 1 组成为强制性的替代方案(demo):
Pattern.compile("example.*?(\".*?\"|'.*?')"
或者带有缓和的贪婪令牌(demo)的变体,可以摆脱交替:
Pattern.compile("example.*?(([\"'])(?:(?!\\2).)*\\2)"
或者,更好的是,支持转义序列(另一个演示):
Pattern.compile("example.*?(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\"|'[^'\\\\]*(?:\\\\.[^'\\\\]*)*')"
在所有 3 个示例中,您只需要访问第 1 组。如果只能(
在example
and "
or之间存在'
,则应替换.*?
为,\(
因为它会使匹配更安全。虽然,使用正则表达式匹配字符串文字(至少使用一个正则表达式)永远不会太安全。
推荐阅读
- json - TypeScript 和 JSON 以及对象中的对象列表?
- android - 为什么触发 Firebase onDataChange() 方法后,我的 Google Map 会不断创建新的地图实例?
- php - 如何使用php函数将mysql查询输出到csv更改列值
- angular - 如何使用拦截器添加 api_key
- python - 无法使用 pylint 导入“app.xxx”(vscode、virtualenv)
- javascript - 如何在反应js中换行后使文本对齐
- c# - 从 Azure Dev Ops 向 Azure Web App Service 进行身份验证
- java - 单击图像时不出现对话框片段
- excel - 如何将我的 Excel DocumentProperty 对象变量(位于 ByRef 函数中)设置为 Word BuiltinDocumentProperties 集合项?
- javascript - 正则表达式 - 查找除某些模式之外的所有唯一字符串