Подтвердить что ты не робот

Почему оператор регулярного выражения() в регулярных выражениях JavaScript не дает мне двух совпадений?

Вот мое регулярное выражение:

"button:not([DISABLED])".match(/\([^()]+\)|[^()]+/g);

Результат:

["button:not", "([DISABLED])"]

Правильно ли это? Я смущен. Поскольку оператор (pipe) | означает "или", я считаю, что правильный результат:

["button:not", "[DISABLED]", "([DISABLED])"] 

Потому что это:

["button:not", "[DISABLED]"]

является результатом:

"button:not([DISABLED])".match(/[^()]+/g);

и это:

["([DISABLED])"]

является результатом:

"button:not([DISABLED])".match(/\([^()]+\)/g);

Но результат вывода в консоли скажет мне, что результат:

["button:not", "([DISABLED])"]

Где проблема?

4b9b3361

Ответ 1

Регулярное выражение

/\([^()]+\)|[^()]+/g

В основном говорит: Есть два варианта: match (1) \([^()]+\) или (2) [^()]+, где бы вы ни находились (/g).

Позвольте перебирать строку с образцом, чтобы вы определили причину полученного результата.

Начальная строка: button:not([DISABLED]).

  • Курсор начинается с char b (на самом деле он начинается с якоря начала строки, ^, но для этого примера это не имеет значения).
  • Между двумя доступными параметрами b может соответствовать только (2), так как (1) требует запуска (.
    • Теперь, когда он начал сопоставляться с (2), он пройдет весь путь, то есть будет потреблять все, что не является ( или ).
    • Из вышеприведенного элемента он потребляет все до t char (потому что следующий ( и не соответствует [^()]+), таким образом оставляя button:not в качестве первой согласованной строки.
  • (комната для ясности)
  • Теперь курсор находится в (. Он начинает соответствовать любому из вариантов? Да, первый: \([^()]+\).
    • Опять же, теперь, когда он начал соответствовать (1), он пройдет весь путь, то есть будет потреблять все, что не является ( или ) до, он находит ) (если при потреблении он находит ( до ), он будет возвращаться, поскольку это будет означать, что регулярное выражение (1) не было согласовано).
    • Теперь он потребляет все остальные символы, пока не найдет ), , а затем ([DISABLED]) в качестве второй строки с согласованием.
  • (комната для ясности)
  • Поскольку мы достигли последнего символа, обработка регулярного выражения заканчивается.



Изменить: Там очень полезный онлайн-инструмент, который позволяет вам видеть регулярное выражение в графической форме. Может быть, это помогает понять, как будет работать регулярное выражение:

Regular expression image

Вы также можете переместить курсор шаг за шагом и посмотреть, что я пытался объяснить выше: прямая ссылка.

Обратите внимание на приоритет выражений, разделенных символом |:. В связи с тем, как движок JavaScript regex обрабатывает строки, порядок, в котором эти выражения кажутся важными. Он будет оценивать каждую альтернативу в том порядке, в котором они указаны. Если один из этих параметров согласован до конца, он не будет пытаться сопоставить любой другой вариант, даже если это возможно. Надеемся, что пример упростит:

"aaa".match(/a|aa|aaa/g); // ==> ["a", "a", "a"]
"aaa".match(/aa|aaa|a/g); // ==> ["aa", "a"]
"aaa".match(/aaa|a|aa/g); // ==> ["aaa"]

Ответ 2

Ваше понимание оператора чередования представляется неправильным. Он не ищет все возможные совпадения, только для первого, который соответствует (слева направо).

Рассмотрим (a | b) как "match либо a , либо b".

Смотрите также: http://www.regular-expressions.info/alternation.html

Ответ 3

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

Итак, оператор | говорит: "Дайте мне что-то, что соответствует левому регулярному выражению или что-то, что соответствует правильному регулярному выражению".

Как ваша строка содержит что-то, что соответствует левому регулярному выражению, вы просто получите это.

Ответ 4

Regex находит наилучшее совпадение, а не все возможные совпадения. Наилучшее совпадение для этого регулярного выражения "([DISABLED])", а не "[DISABLED]", которое является подмножеством "лучшего" совпадения.

Рассмотрим следующий пример:

"123 456789".match( /[0-9]{4,6}/g )

Вы хотите найти один номер длиной от 4 до 6 цифр. Если результатом будут все возможные числа, соответствующие регулярному выражению, это не будет иметь особого значения:

[ "4567", "5678", "6789", "45678", "56789", "456789" ]   // you don't want this