Java: RegExp для совпадения слов в кавычках - PullRequest
2 голосов
/ 23 марта 2020

У меня есть следующая тестовая строка

This is my "te

st" case
with lines for "tes"t"ing" with regex
But as he said "It could be an arbitray ammount of words"

И я хочу сопоставить все, что находится между ", пока оно связано со словами. У меня есть следующее регулярное выражение:

\"([^\"]*)\"

, которое очень хорошо соответствует словам "test", даже если оно разделено. Есть ли способ найти tes"t"ing, а также целое слово (и не разделить его на два слова?) Попытка с границами слова \b (\b\"([^\"]*)\"\b) не очень хорошо работает, потому что она не будет соответствовать самый первый " и только что упомянутая группа.

Мне нужно это для Java регулярное выражение.

ОБНОВЛЕНИЕ В результате мне нужно иметь

This is my \q{te

st} case
with lines for \q{tes"t"ing} with regex
But as he said \q{It could be an arbitray ammount of words}

Ответы [ 3 ]

2 голосов
/ 24 марта 2020

Вы можете использовать регулярное выражение

(?<=\")(?:[a-z]+\"[a-z]+\"[a-z]+|[a-z][^"]+)(?=\")

с флагом безразличного регистра i (или предисловие с (?i)).

Демо

Как видно по ссылке, это регулярное выражение соответствует следующим трем подстрокам текста, приведенного в вопросе:

te                                                                    st
tes"t"ing
It could be an arbitray ammount of words

Механизм регулярных выражений выполняет следующие операции:

(?<=\")    # match a double-quote in a positive lookbehind
(?:        # begin a non-capture group
  [a-z]+\" # match 1+ letters, then a double-quote
  [a-z]+\" # match 1+ letters, then a double-quote
  [a-z]+   # match 1+ letters
  |        # or
  [a-z]    # match 1 letter
  [^"]+    # match 1+ characters other than a double-quote
)          # end non-capture group
(?=\")     # match a double-quote in a positive lookahead
2 голосов
/ 24 марта 2020

Вы можете использовать

.replaceAll("\\B\"\\b(.*?)\\b\"\\B", "\\\\q{$1}")

Или, если совпадения могут охватывать несколько строк, добавить модификатор (?s):

.replaceAll("(?s)\\B\"\\b(.*?)\\b\"\\B", "\\\\q{$1}")

См. Демонстрационную версию regex .

Подробности

  • \B"\b - ", который находится в начале строки или предшествует несловесному символу, и за ним следует слово char
  • (.*?) - группа 1: любые ноль или более символов, кроме символов перевода строки, как можно меньше
  • \b"\B - " то есть либо в конце строки, либо с последующим введением не-слова char, и перед ним стоит слово char.

Замена - обратная косая черта sh ("\\\\", примечание Двойной литерал backsla sh необходим в замещающей части регулярного выражения для вставки реального литерала backsla sh, поскольку backsla sh - это специальный символ в шаблоне замены), q{, значение Group1 (* 1031) *) и }.

См. Java демо :

String s = "This is my \"te\n\nst\" case\nwith lines for \"tes\"t\"ing\" with regex\nBut as he said \"It could be an arbitray ammount of words\"";
System.out.println(s.replaceAll("\\B\"\\b(.*?)\\b\"\\B", "\\\\q{$1}"));

Выход:

This is my "te

st" case
with lines for \q{tes"t"ing} with regex
But as he said \q{It could be an arbitray ammount of words}

Примечание: * 10 45 *

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

 .replaceAll("(?s)\\B(\"\\b(.*?)\\b\"|\"\")\\B", "\\\\q{$2}")

См. regex demo .

Подробности

  • (?s) - опция встроенного флага (равная Pattern.DOTALL), которая делает . совпадение символы разрыва строки тоже
  • \B - граница, не состоящая из слов, здесь это означает, что непосредственно слева должен быть символ, не состоящий из слов или начало строки (потому что после \B, есть не-слово char, ")
  • ( - начало первой группы захвата:
    • "\b(.*?)\b" - ", за которым следует слово char, затем Group 2 захватывая ноль или более символов, как можно меньше, а затем ", которому предшествует слово char (вот почему этот шаблон не может соответствовать "", поскольку после первого и перед вторым должен быть буквой, ди git или _)
    • | - или
    • "" - "" подстрока
  • ) - конец первой группы захвата
  • \B - граница без слов, здесь это означает, что сразу направо, там должен быть не состоящим из слова char или концом строки (потому что до \B есть не-слово char, ").
2 голосов
/ 23 марта 2020

Вы можете использовать это регулярное выражение, которое использовало lookbehind и lookahead, чтобы гарантировать, что предыдущий и следующий символы не являются непробельными символами:

(?<!\S)".*?"(?!\S)

Демонстрация RegEx

Добавление полезного комментария от OP, который работал, чтобы решить проблему, которая была немного больше, чем то, что было упомянуто в вопросе:

str = str.replaceAll("(?s)(?<!\\S)\"(.*?)\"(?!\\S)", "\\\\q{$1}"); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...