_STRING_ESC_INNER
: мы хотим, чтобы это совпадало с максимально короткой строкой, которая не содержит закрывающей кавычки , То есть для ввода "abc"xyz"
мы хотим соответствовать "abc"
, вместо того, чтобы потреблять часть xyz"
. Тем не менее, мы должны убедиться, что "
действительно заключительная кавычка, так как она не должна быть сама по себе экранирована. Поэтому для ввода "abc\"xyz"
мы не хотим сопоставлять только "abc\"
, потому что \"
экранирован. Мы видим, что закрытию "
должно предшествовать четное число \
(при этом ноль является четным числом). Итак, "
в порядке, \\"
в порядке, \\\\"
в порядке и т.д. c. Но как только "
предшествует нечетное число \
, это означает, что "
на самом деле не является заключительной кавычкой.
(\\\\)
соответствует \\
. (?<!\\)
говорит, что "позиция до этого не должна иметь \
". Таким образом, объединенный (?<!\\)(\\\\)
означает «соответствует \\
, но только если ему не предшествует \
».
Следующий *?
затем делает наименьшее возможное повторение этого, что опять же имеет смысл при рассмотрении следующего за ним регулярного выражения, которое является "
из правила ESCAPED_STRING
(возможная путаница: \"
в ESCAPED_STRING
относится к литералу "
в фактическом вводе, который мы хотим чтобы соответствовать, так же, как \\\\
относится к \\
на входе). Таким образом, (?<!\\)(\\\\)*?\"
означает «соответствовать кратчайшему количеству \\
, за которым следует "
, а не предшествует \
. Другими словами, (?<!\\)(\\\\)*?\"
соответствует только "
, которому предшествует четное число \
(включая блоки размером 0).
Теперь объединяя его с предшествующим _STRING_INNER
, правило _STRING_ESC_INNER
затем говорит: Сопоставьте first "
, которому предшествует четное число \
, то есть, другими словами, первый "
, где \
сам по себе не экранирован.