Регулярное выражение, когда шаблон включает в себя знак доллара ($) - PullRequest
0 голосов
/ 23 апреля 2019

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

(en $) foo
oof ($).
ofo (env. 80 $US)

Я использую следующее регулярное выражение:

Pattern p = Pattern.compile(
            "\\([\\p{InARABIC}\\s]+\\)|\\([\\p{InBasic_Latin}\\s?\\$]+\\)|\\)([\\p{InARABIC}\\s]+)\\(",
            Pattern.CASE_INSENSITIVE);

public String replace(String text) {
    Matcher m = p.matcher(text);
        String replacement = m.replaceAll(match -> {
            if (m.group(1) == null) {
                return m.group();
            } else {
                return "(" + match.group(1) + ")";
            }
        });
        return replacement;
    }

, но не могу сопоставить текст, содержащий $

1 Ответ

2 голосов
/ 23 апреля 2019

Этот код похож на replaceAll(regex, replacement).Проблема в том, что $ не только особый в аргументе regex , но также и в замене , где его можно использовать как ссылку для сопоставления из групп, подобных $x (где x является идентификатором группы) или ${groupName}, если ваше регулярное выражение имеет (?<groupName>subregex).

Это позволяет нам писать код, подобный

String doubled = "abc".replaceAll(".", "$0$0");
System.out.println(doubled); //prints: aabbcc

, который заменит каждый символ двумя его копиями, поскольку каждый символ будет сопоставляться с . и помещаться в группу 0, поэтому $0$0 представляет два повторения этого сопоставленного символа.

Но в вашем случае у вас есть $ в вашем text, поэтому, когда он совпадает, вы заменяете его на себя, поэтому вы используете вместо $ без какой-либо информации об идентификаторе группы (или имени группы), что приводит к IllegalArgumentException: Illegal group reference.

Решение состоит в том, чтобы избежать этого $ в замене часть .Вы можете сделать это вручную, с помощью \, но лучше использовать метод, разработанный для этой цели Matcher#quoteReplacement (в случае, если регулярное выражение будет развиваться, и вам нужно будет избегать больше вещей, этот метод должен развиватьсявместе с движком регулярных выражений, который впоследствии избавит вас от неприятностей)

Поэтому попробуйте изменить код на

public String replace(String text) {
    Matcher m = p.matcher(text);
        String replacement = m.replaceAll(match -> {
            if (m.group(1) == null) {
                return Matcher.quoteReplacement(m.group());
                //     ^^^^^^^^^^^^^^^^^^^^^^^^
            } else {
                return Matcher.quoteReplacement("(" + match.group(1) + ")");
                //     ^^^^^^^^^^^^^^^^^^^^^^^^
            }
        });
        return replacement;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...