Java ';什么时候开始';在正则表达式中不匹配?
我遇到了以下问题(简化)。我写了以下内容Java ';什么时候开始';在正则表达式中不匹配?,java,regex,Java,Regex,我遇到了以下问题(简化)。我写了以下内容 Pattern pattern = Pattern.compile("Fig.*"); String s = readMyString(); Matcher matcher = pattern.matcher(s); 在读取一个字符串时,匹配器无法匹配,即使它以“Fig”开头。我在字符串的下一部分找到了一个流氓字符。它的代码点值为1633 (int) charAt(i) 但与正则表达式不匹配。我认为这是由于输入过程中的某个地方使用
Pattern pattern = Pattern.compile("Fig.*");
String s = readMyString();
Matcher matcher = pattern.matcher(s);
在读取一个字符串时,匹配器无法匹配,即使它以“Fig”开头。我在字符串的下一部分找到了一个流氓字符。它的代码点值为1633
(int) charAt(i)
但与正则表达式不匹配。我认为这是由于输入过程中的某个地方使用了非UTF-8编码
他们说:
预定义字符类
. 任何字符(可能与行终止符匹配,也可能不匹配)
这可能不是严格意义上的字符,但仍然是字符串的一部分。如何检测此问题
更新:这是由于(字符)10这是不容易发现。我上面的诊断是错误的,下面的所有答案都与所问的问题相关,并且非常有用。Java正则表达式中的
字符与除行终止符以外的任何字符匹配,除非在编译模式时使用标志Pattern.DOTALL
为此,您将使用如下模式:
Pattern p = Pattern.compile("somepattern", Pattern.DOTALL);
检查这一点很容易:
import java.util.regex.*;
public class Test {
public static void main(String[] args) {
Pattern pattern = Pattern.compile(".");
for (char c = 0; c < 0xffff; c++) {
String text = String.valueOf(c);
if (!pattern.matcher(text).matches()) {
System.out.println((int) c);
}
}
}
}
其中,10和13分别为“\n”和“\r”。133(U+0085)是“下一行”,8232(U+2028)是“行分隔符”,8233(U+2029)是“段落分隔符”
请注意:
- 这不会测试基本多语言平面之外的任何Unicode字符
- 它只使用默认选项
- 这似乎与你对1633(U+0661)角色的体验相矛盾
可以有3种稍有不同的解释,具体取决于标志
默认情况下
将在禁用模式和模式时排除(默认):
行终止符是一个一个或两个字符的序列,用于标记输入字符序列行的结束。以下是公认的线路终端:
- 换行符(换行符)字符(
)'\n'
- 紧接着换行符(
)的回车符“\r\n”
- 独立的回车符(
)'\r'
- 下一行字符(
)'\u0085'
- 行分隔符(
),或'\u2028'
- 段落分隔符(
)'\u2029'
相当于[^\n\r\u0085\u2028\u2029]
当启用了UNIX\u行
模式,但禁用了DOTALL
模式时
当启用模式但禁用模式时,
将仅排除\n
。这意味着在这种情况下,
相当于[^\n]
如果模式被激活,则唯一识别的行终止符是换行符
启用DOTALL
模式时
如果启用模式,
将匹配任何字符,无例外
正则表达式
匹配除行终止符以外的任何字符,除非指定了标志
你能举一个由
readMyString()
返回的字符串的例子吗?不,因为我认为它会被剪切和粘贴损坏(有问题的字符不会打印),我用“Fig\u0661”
试过,它匹配正确。@Howard是的-如果你自己构造字符串,它就可以工作。到1633,你是说1633(十进制)吗或者0x661(十六进制):?检查是一种方法,但是文档在这一点上应该足够清楚。@nhahdh:是的,这是公平的。查看哪些字符算作换行符很有用:)您还可以使用模式字符串开头的(?s)
将选项表示为标志,如下所述:。如果使用更紧凑的语法,或者在我的例子中使用Scala,这可能会更方便。
10
13
133
8232
8233