java—从文件中读取字符串并将其转换为文本正则表达式
我有一段代码,其中我向hashmap插入了一个模式键和一个字符串标记:java—从文件中读取字符串并将其转换为文本正则表达式,java,regex,Java,Regex,我有一段代码,其中我向hashmap插入了一个模式键和一个字符串标记: while( (word = reservedWordsRead.readLine()) != null ) { String[] k = word.split(" "); infoList.put(Pattern.compile("^("+k[0]+")"), //lexeme k[1]); //token } 它读取的文件如下所示: ) rparen (
while( (word = reservedWordsRead.readLine()) != null ) {
String[] k = word.split(" ");
infoList.put(Pattern.compile("^("+k[0]+")"), //lexeme
k[1]); //token
}
它读取的文件如下所示:
) rparen
( lparen
\\) rparen
\\( lparen
while( (word = reservedWordsRead.readLine()) != null ) {
String[] k = word.split(" ");
infoList.put(Pattern.compile("^("+Pattern.quote(k[0])+")"), //lexeme
k[1]); //token
}
但是括号无法识别,所以我修改了文件,使其看起来像这样:
) rparen
( lparen
\\) rparen
\\( lparen
while( (word = reservedWordsRead.readLine()) != null ) {
String[] k = word.split(" ");
infoList.put(Pattern.compile("^("+Pattern.quote(k[0])+")"), //lexeme
k[1]); //token
}
代码如下:
) rparen
( lparen
\\) rparen
\\( lparen
while( (word = reservedWordsRead.readLine()) != null ) {
String[] k = word.split(" ");
infoList.put(Pattern.compile("^("+Pattern.quote(k[0])+")"), //lexeme
k[1]); //token
}
但是我没有得到正确的输出。什么都不匹配。此外,rparen和lparen插入到hashmap中,因为我可以使用我的tokenizer()方法打印以下内容:
这是我的标记器方法:
pattern: ^(\Q\\)\E), token: rparen
pattern: ^(\Q\\(\E), token: lparen
public void tokenize(String str) {
String s = str.trim();
tokenList.clear();
while (!s.equals("")) {
boolean match = false;
for ( Entry<Pattern,String> thing: infoList.entrySet() ) {
System.out.println("pattern: "+thing.getKey().toString()+", token: "+thing.getValue());
Matcher m = thing.getKey().matcher(s);
if (m.find()) {
match = true;
String tok = m.group().trim();
s = m.replaceFirst("").trim();
tokenList.put(tok,thing.getValue());
break;
}
} if (!match)
throw new ParserException("Unexpected character in input: "+s);
}
}
public void标记化(String str){
字符串s=str.trim();
tokenList.clear();
而(!s.equals(“”){
布尔匹配=假;
for(条目内容:infoList.entrySet()){
println(“模式:+thing.getKey().toString()+”,标记:+thing.getValue());
Matcher m=thing.getKey().Matcher;
if(m.find()){
匹配=真;
字符串tok=m.group().trim();
s=m.replaceFirst(“”.trim();
tokenList.put(tok,thing.getValue());
打破
}
}如果(!匹配)
抛出新的ParserException(“输入中的意外字符:“+s”);
}
}
我不确定我做错了什么。。非常感谢您的帮助:)
\)rparen
在文件中就像在java字符串中一样“…\)…”
反斜杠必须加倍以表示反斜杠。这样就不需要quote
,它也可以做得更具体一些。如果要匹配精确的字符串,应该使用Pattern.quote()
遇到的问题是,您试图引用传递的字符串并转义括号,本质上是双重转义(让人想起HTML中的&;amp;
)。虽然可以将所有特殊转义字符放入输入文件中,但为什么还要麻烦呢?让Pattern
为您完成这项工作
这里有一个测试,我们尝试几个不同的输入,并尝试将它们转换为模式
,就像您所做的那样
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class RegexTest
{
private static final String[] TESTS = {"a","(","\\(","\\\\(","[letters]"};
public static void main(String[] args) {
for(String test : TESTS) {
examineRegex(test);
System.out.println();
}
}
public static void examineRegex(String match) {
System.out.println("Testing "+match);
String template = "^(%s)";
String regex = String.format(template, match);
examinePattern(match, regex);
String quotedRegex = String.format(template, Pattern.quote(match));
examinePattern(match, quotedRegex);
}
public static void examinePattern(String match, String regex) {
try {
Pattern pattern = Pattern.compile(regex);
System.out.println(" Compiled: "+pattern);
System.out.println(" Match?: "+pattern.matcher(match).matches());
} catch (PatternSyntaxException e) {
System.out.println(" Failed to compile: "+e.getMessage()
.substring(0, e.getMessage().indexOf('\n')));
}
}
}
该程序的输出如下(注释内联):
对于“普通”字符串的简单情况,原始方法和usingPattern.quote()
都有效。到目前为止还不错
Testing (
Failed to compile: Unclosed group near index 4
Compiled: ^(\Q(\E)
Match?: true
但是如果我们传入一个构造,比如(
),我们会得到一个错误,除非我们引用它
Testing \(
Compiled: ^(\()
Match?: false
Compiled: ^(\Q\(\E)
Match?: true
如果我们传入一个转义的构造,原始模式会成功编译,但与输入字符串不匹配。这不是世界末日——它会匹配(
),但这是违反直觉的;它破坏了我们对传入的是我们匹配的东西的期望
Testing \\(
Failed to compile: Unclosed group near index 6
Compiled: ^(\Q\\(\E)
Match?: true
现在,我们双重转义一个模式,就像试图将输入当作Java字符串一样。这表明,在试图准确确定需要转义多少时,可能会产生混淆
Testing [letters]
Compiled: ^([letters])
Match?: false
Compiled: ^(\Q[letters]\E)
Match?: true
最后,假设我们想要匹配一个字符串,它也是一个实际的正则表达式?它将成功编译,因此无法提醒我们该问题,但将无法匹配预期的字符串
正如您所看到的,Pattern.quote()
每次都有效,避免了将正则表达式的实现细节放入数据文件中。这样,您就可以从文本文件中隐藏匹配实际发生方式的实现细节,这种划分会产生健壮的代码
当然,如果文件中需要的是正则表达式列表,那么显然不希望使用
Pattern.quote()
,而您需要让用户清楚地知道,输入需要是有效的Java正则表达式,并且提供糟糕的模式可能会导致潜在的混乱结果。您能否向这位困惑不解的读者解释一下您所说的“它也做得更间接一点”是什么意思你可以自己做一个System.out.println(Pattern.quote(“”);
如果我做对了,它会给出\Q(\E
。哇,这非常有用。我也不想在我的文件中列出正则表达式。谢谢。。