Вопрос по java, regex – Экранирование специальных символов в регулярных выражениях Java

19

Есть ли какой-либо метод в Java или любая библиотека с открытым исходным кодом для экранирования (без кавычек) специального символа (метасимвола), чтобы использовать его в качестве регулярного выражения?

Это было бы очень удобно при динамическом построении регулярного выражения, без необходимости вручную экранировать каждый отдельный символ.

Например, рассмотрим простое регулярное выражение типа\d+\.\d+ который соответствует числам с десятичной точкой, как1.2, а также следующий код:

String digit = "d";
String point = ".";
String regex1 = "\\d+\\.\\d+";
String regex2 = Pattern.quote(digit + "+" + point + digit + "+");

Pattern numbers1 = Pattern.compile(regex1);
Pattern numbers2 = Pattern.compile(regex2);

System.out.println("Regex 1: " + regex1);

if (numbers1.matcher("1.2").matches()) {
    System.out.println("\tMatch");
} else {
    System.out.println("\tNo match");
}

System.out.println("Regex 2: " + regex2);

if (numbers2.matcher("1.2").matches()) {
    System.out.println("\tMatch");
} else {
    System.out.println("\tNo match");
}

Не удивительно, что результат, полученный с помощью приведенного выше кода:

Regex 1: \d+\.\d+
    Match
Regex 2: \Qd+.d+\E
    No match

То есть,regex1 Матчи1.2 ноregex2 (который "динамически" построен) не (вместо этого он соответствует литеральной строкеd+.d+).

Итак, есть ли метод, который будет автоматически экранировать каждый метасимвол регулярного выражения?

Если бы был, скажем, статическийescape() метод вjava.util.regex.Pattern, выход

Pattern.escape('.')

будет строка"\.", но

Pattern.escape(',')

должен просто произвести",", поскольку это не метасимвол. Так же,

Pattern.escape('d')

может производить"\d", поскольку'd' используется для обозначения цифр (хотя в этом случае экранирование может не иметь смысла, так как'd' может означать буквальный'd'который не будет неправильно понят интерпретатором регулярных выражений как нечто иное, как в случае с'.').

Чтобы избежать только отдельных символов, вы можете поиграть с соответствием границам слов, например:s/\b([dswDSW])\b/\\$1/g; rsp
Правильно, именно поэтому я спрашиваю метод, который будет экранировать отдельные символы! :-) PNS
Можете ли вы сделать шаг назад и объяснитьwhy Вы хотите этот метод? Почему бы вам просто не использовать & quot; \\ d & quot ;? Если вы знаете, что хотите цифру, почему бы просто не иметь константную строку, которая делает это. Зачем нужен целый метод, который просто добавляет & quot; \\ & quot ;? Gray
Как такой метод будет определять разницу междуd подразумевается как мета персонаж иd в тексте, чтобы соответствовать? (quote("d+ Dollars?") станет"\\d+ \\Dollar\\s?" в тривиальном методе цитирования.) rsp
Конечно, существует множество способов сделать это «вручную». (даже имея таблицу символов и сравнивая каждый раз), но я по сути спрашиваю, сделал ли это кто-то уже. PNS

Ваш Ответ

6   ответов
6

с помощью которого сопоставитель регулярных выражений знает, что вы ищете цифру, а не буквуd это избежать письма (\d). Чтобы ввести escape-символ regex в java, вам нужно его экранировать (так\ становится\\). Таким образом, невозможно набрать двойной обратный слеш для специальных символов регулярного выражения.

Именно поэтому я хочу метод, который бы экранировал символ в строку регулярного выражения (то есть, не литерал). PNS
Вы можете написать свой собственныйescape() метод, который prepends"\\" по своему параметру
Чтобы понять терминологию, добавление обратной косой черты к не специальному символу не называется экранированием. Написать\d ни в коем случае не "избегать буквы"d, Вместо этого он создает совершенно отличную концепцию, класс символов, который представляет цифры. Примером экранирования может служить ваш второй случай: «\» для представления символа косой черты.
0

escapeQuotes() чтобы избежать струн междуGroups а такжеSets изRegualrExpression.

List of Regex Literals to escape <([{\^-=$!|]})?*+.>

public class RegexUtils {
    static String escapeChars = "\\.?![]{}()<>*+-=^$|";
    public static String escapeQuotes(String str) {
        if(str != null && str.length() > 0) {
            return str.replaceAll("[\\W]", "\\\\$0"); // \W designates non-word characters
        }
        return "";
    }
}

From the Pattern класс обратной косой черты('\') служит для введения экранированных конструкций. Строковый литерал"\(hello\)" является недопустимым и приводит к ошибке во время компиляции; чтобы соответствовать строке (привет) строковый литерал"\\(hello\\)" должен быть использован.

Example: Строка для сопоставления(hello) и регулярное выражение с группой(\(hello\)), Форма здесь вам нужно только экранировать совпадающую строку, как показано ниже.Test Regex online

public static void main(String[] args) {
    String matched = "(hello)", regexExpGrup = "(" + escapeQuotes(matched) + ")";
    System.out.println("Regex : "+ regexExpGrup); // (\(hello\))
}
24

Pattern SPECIAL_REGEX_CHARS = Pattern.compile("[{}()\\[\\].+*?^$\\\\|]");

И используйте это в этом методе:

String escapeSpecialRegexChars(String str) {

    return SPECIAL_REGEX_CHARS.matcher(str).replaceAll("\\\\$0");
}

Тогда вы можете использовать его, например, так:

Pattern toSafePattern(String text)
{
    return Pattern.compile(".*" + escapeSpecialRegexChars(text) + ".*");
}

Нам нужно было сделать это, потому что после экранирования мы добавили некоторые выражения регулярных выражений. Если нет, вы можете просто использовать\Q а также\E:

Pattern toSafePattern(String text)
{
    return Pattern.compile(".*\\Q" + text + "\\E.*")
}
Этот не работал для меня (по крайней мере, в Scala), но этот работал:"[\\{\\}\\(\\)\\[\\]\\.\\+\\*\\?\\^\\$\\\\\\|]"
Вот полный список специальных символов здесь:stackoverflow.com/a/27454382/1490986
23

ot quoting) a special character (meta-character), in order to use it as a regular expression?

Я не уверен на 100%, что это то, о чем вы спрашиваете здесь. Если вы ищете способ создания констант, которые вы можете использовать в шаблонах регулярных выражений, просто добавьте их с помощью"\\" должно работать но нет приятногоPattern.escape('.') Функция, чтобы помочь с этим.

Так что если вы пытаетесь соответствовать"\\d" (строка\d вместо десятичного знака) тогда вы бы сделали:

// this will match on \d as opposed to a decimal character
String matchBackslashD = "\\\\d";
// as opposed to
String matchDecimalDigit = "\\d";

4 косые черты в строке Java превращаются в две косые черты в шаблоне регулярных выражений. 2 обратные косые черты в шаблоне регулярных выражений совпадают с самой обратной косой чертой. Добавление любого специального символа с обратной косой чертой превращает его в обычный символ вместо специального.

matchPeriod = "\\.";
matchPlus = "\\+";
matchParens = "\\(\\)";
... 

В своем посте вы используетеPattern.quote(string) method, Вы, наверное, знаете, что это оборачивает ваш паттерн между"\\Q" а также"\\E" так что вы можете сопоставить строку, даже если в ней есть специальный символ регулярного выражения (+, ., \\d, так далее.)

Я знаю о quote (), и если вы посмотрите на пример выходных данных выше, он включает в себя \ Q и \ E. На самом деле, я просто искал метод для создания экранированной версии символа для регулярного выражения Java. Так, например, экранированная запятая останется запятой, но экранированная точка должна стать \. и так далее. PNS
0

pattern.compile("\"");
String s= p.toString()+"yourcontent"+p.toString();

даст результат какyourcontent как есть

1

так как вам может потребоваться, чтобы в вашем шаблоне были как литралы (\ [, \]), так и метасимволы ([,]). таким образом, с помощью некоторой утилиты вы сможете сначала экранировать все символы, а затем можете добавить метасимволы, которые вы хотите добавить в тот же шаблон.

Похожие вопросы