我遇到了以下问题(简化)。我写了以下
Pattern pattern = Pattern.compile("Fig.*");
String s = readMyString();
Matcher matcher = pattern.matcher(s);
在读取一个字符串时,匹配器无法匹配,即使它以“图”开头。我将问题跟踪到字符串下一部分中的流氓角色。它的代码点值为1633来自
(int) charAt(i)
但与正则表达式不匹配。我认为这是由于输入过程中某处出现了非UTF-8编码。
Javadocs说:
预定义的字符类 。任何字符(可能与行终止符匹配也可能不匹配)
据推测,这不是严格意义上的字符,但仍然是字符串的一部分。我如何检测到这个问题?
更新:这是由于(char)10不容易发现。我上面的诊断是错误的,下面的所有答案都与所提出的问题相关并且很有用。
答案 0 :(得分:13)
检查这个很容易:
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
133
8232
8233
其中,10和13分别是“\ n”和“\ r”。 133(U + 0085)是“下一行”,8232(U + 2028)是“行分隔符”,8233(U + 2029)是“段落分隔符”。
请注意:
答案 1 :(得分:11)
Java正则表达式中的.
字符匹配除行终止符之外的任何字符,除非在编译模式时使用标记Pattern.DOTALL
。
为此,您可以使用这样的模式:
Pattern p = Pattern.compile("somepattern", Pattern.DOTALL);
答案 2 :(得分:2)
根据documentation,.
可以有 3略有不同的解释,具体取决于标记。
DOTALL
模式时, .
会排除UNIX_LINES
(默认):
行结束符是一个单字符或双字符序列,用于标记输入字符序列行的结尾。以下被认为是行终止符:
- 换行符(换行符)(
'\n'
),- 回车符后面紧跟换行符(
"\r\n"
),- 一个独立的回车符(
'\r'
),- 下一行字符(
'\u0085'
),- 行分隔符(
'\u2028'
)或- 段落分隔符(
'\u2029'
)。
这意味着.
在这种情况下相当于[^\n\r\u0085\u2028\u2029]
。
UNIX_LINES
模式但禁用DOTALL
模式UNIX_LINES
模式后, .
将仅排除 \n
,但会禁用DOTALL
模式。这意味着.
在这种情况下相当于[^\n]
。
如果激活
UNIX_LINES
模式,则识别的唯一行终止符是换行符。
DOTALL
模式时如果启用了DOTALL
模式,.
将匹配任何字符,无例外。
正则表达式
.
匹配除行终止符之外的任何字符,除非指定了DOTALL
标志。
答案 3 :(得分:1)
关于使用正则表达式非打印字符,您可以阅读以下两篇文章: