转义字符类中的单个字符

时间:2015-01-06 02:25:57

标签: java android regex escaping

如何在Java中转义单个正则表达式元字符?

对于Android应用,我正在使用包含许多正则表达式认为具有特殊含义的字符的文件。其中包括\?.()[*\^+'-。我将阅读两个文件:

  1. 单词的字典列表,每个单独的行。
  2. 可用于过滤字典列表中单词的字符列表。
  3. 每个样本如下。

    字典:

     /it*
     t1*]
     ?\<t
     item
    

    (是的,这些是单词。前三个是合同Braille ASCII表示的单词&#34; stitch&#34;,&#34; teacher&#34;,&#34; think&# 34;现在你知道了。)

    &#34;信函和#34;使用:

    ?]*/\<1eitm
    

    我希望将这些字母包含在与此类似的正则表达式中:

    String letters = "?]*/\<1eitm";
    Pattern pattern = Pattern.compile("^["+letters+"]{4}$", Pattern.MULTILINE);
    

    我的目标是从词典列表中选择仅包含给定字符的所有单词是给定的长度。我无法控制请求的字符在文件中出现的顺序。

    如果我只使用非元字符,例如<1eitm,这样可以正常工作。不知何故,我需要转义元字符,并确保]-等字符出现在方括号内的正确位置。

    我可以手动执行此操作...但我希望有一个内置命令为我这样做。到目前为止我找到的只是Pattern.quote()命令,它没有给我我想要的结果。

    下面是我可能需要在方括号内使用的所有字符的列表:

    \_-,;:!?.'"()[]@*/\&#%^+<=>~$0123456789abcdefghijklmnopqrstuvwxyz
    

    这是我用于Android测试的准系统代码:

    package com.example.quote;
    
    import android.app.Activity;
    import android.content.res.AssetManager;
    import android.os.Bundle;
    import android.util.Log;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            AssetManager am = this.getAssets();
            try {
                String dictionary = readFile(am, "dictionary.txt");
                String regex = readFile(am, "regex.txt");
    
                regex = "^["+regex+"]{4}$"; // THIS IS WHERE I NEED TO MAKE A CHANGE
    
                Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
                Matcher matcher = pattern.matcher(dictionary);
    
                while (matcher.find()) {
                    Log.d("TEST", matcher.group(0));
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        private String readFile(AssetManager am, String fileName) throws IOException {
            InputStream is = am.open(fileName);
    
            int size = is.available();
            byte[] buffer = new byte[size];
            is.read(buffer);
            is.close();
    
            String string = new String(buffer, "UTF-8");
    
            return string;
        }
    }
    

2 个答案:

答案 0 :(得分:1)

使用Pattern.quote()引用所有特殊字符并使它们与文字字符匹配。该函数通常通过包含引号\Q...\E construct。

提供的String来实现

在Oracle / OpenJDK(引用)实现中,它围绕带有\Q...\E构造的String,引用的构造在Java 6的字符类中被识别,因此返回的值可以在字符类中使用。

Android使用ICU implementation,根据文档,它还允许\Q\E在字符类中工作。因此,无论Pattern.quote()函数如何在ICU中工作(添加转义\或使用引用\Q...\E构造),它都应该在这方面与参考实现(Java 6)类似。

regex = "^[" + Pattern.quote(regex) + "]{4}$";

答案 1 :(得分:0)

转义Java正则表达式的特殊字符很烦人,但并不困难。原因是反斜杠字符\是Java字符串中的转义字符,因此文字字符串&#34; \&#34;是反斜杠。但是单个反斜杠也是正则表达式中的转义字符,因此在Java正则表达式模式匹配字符串中,特殊字符应该被&#34;转义&#34;用双反斜杠!因此,为了匹配问号字符?,您的正则表达式必须包含\\?。要匹配单个反斜杠,您的正则表达式必须包含\\\\

让我们以String为例:

String letters = "?]*/\<1eitm";

这里的前五个字符应该被转义 - 也就是说,前缀为双反斜杠转义序列\\

String letters = "\\?\\]\\*\\/\\\\<1eitm";

如上所述,反斜杠本身必须以转义序列为前缀,然后加倍。

希望这有帮助。