Регулярное выражение Javascript для сопоставления между двумя шаблонами, где первый шаблон необязателен

#javascript #regex

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

Вопрос:

Я перепробовал так много вещей и попытался адаптировать похожие ответы… но все еще потерян сегодня из-за этого, если кто-нибудь может помочь, я был бы бесконечно благодарен!

Мне нужно использовать регулярное выражение (используемая мной библиотека JS lexer не допускает ничего другого) для сопоставления:

  • Любое содержимое между $$ и */
  • Не должно включать открытие $$
  • Но должен включать закрытие */
  • «Содержимое» может быть любым символом / цифрой / пробелом / новой строкой

Учитывая это:

 xxx. 123 $$yyy.234 */zzz.567
           ^^^^^^^^^^

  

…Мне нужно, чтобы указанная строка соответствовала.

Таким образом, это, кажется, работает нормально:

 (?<=$$)(?:[sS])*?(?:[sS])*?*/
  

(… как видно здесь)

Но есть дополнительное требование:

  • Если его нет $$ , то просто сопоставьте с началом строки.

Например.:

 xxx. 123 yyy.234 */zzz.567
^^^^^^^^^^^^^^^^^^^
  

Да, на пределе моих знаний о регулярных выражениях и просто не могу его использовать! 🙁

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

 $[p{L}0-9_]*?$
  

Комментарии:

1. Согласно вашему описанию, шаблон может выглядеть как /(?<=$$|^).*?*//s

2. » Возможно, стоит упомянуть «, действительно существуют важные различия между шаблоном, который соответствует только одному символу, шаблоном, который соответствует только фиксированному количеству символов, и шаблоном, который соответствует переменному количеству символов.

Ответ №1:

При сопоставлении с www $$ xxx $$ yyy */ zzz я предполагаю, что результат должен быть $$ yyy */ , а не $$ xxx $$ yyy */ . Решение может быть более сложным, чем должно быть, если это не является обязательным требованием.


 (?: ^ | $$ )        # Starting at the start of the string or at "$$"
( (?: (?!$$). )*    # A sequence of characters (.) now of which starting with "$$"
  */                 # Followed by "*/"
)                     # End capture
  

За исключением того, что не совсем. Это не сработает для $$$abc*/ . Итак, мы исправляем:

 (?: ^ | $$(?!$) )  # Starting at the start of the string or at "$$" (but not "$$$")
( (?: (?!$$). )*    # A sequence of characters (.) now of which starting with "$$"
  */                 # Followed by "*/"
)
  

Мы также могли бы избежать поиска.

 (?: ^ | $$ )
( (?: [^$]  ( $[^$]  )* $? )?
  */
)
  

Что касается обновленного вопроса, предварительная версия может быть изменена для размещения $[p{L}0-9_]*$ .

 (?: ^
|   $ [p{L}0-9_]* $ (?! [p{L}0-9_]* $ )
)
( (?: (?! $ [p{L}0-9_]* $ ) . )*
  */
)
  

Я использовал разрывы строк и пробелы для удобства чтения. Вам нужно будет удалить их (поскольку движок JS, похоже, не имеет флага, чтобы заставить их игнорироваться, как это делают некоторые другие движки).

Комментарии:

1. Обновленный ответ.

2. Привет @ikegami, спасибо тебе за это, извиняюсь, ты видел мою предыдущую правку? Требования к символу $ $ немного более смягчены, чем первоначально заявлено … он может содержать буквы, цифры и символ _ между долларами. Итак, все это допустимые символы открытия: $$, $hello $, $ hello123 $, $ hello_123 $. Спасибо за помощь, извините, я не понимал, что это повлияет на решение так сильно, как оно есть. К сожалению, я все еще не могу заставить его работать.

3. Это работает как шарм @ikegami, большое вам спасибо!

Ответ №2:

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

 let str = "xxx. $$ 123 $$yyy.234 */zzz.567";
let regex = /$?w*$?([w d.-]*$?[w d.-]**/)/gm;

console.log(regex.exec(str)[1]);
  

Обновить:
Как упоминалось в комментариях, приведенный выше метод не работает для a $ b */ типа строк. Итак, я придумал это. Это не так хорошо, как у @ikugami, но это определенно может быть другим способом.

 let str = "$$xxx. $$gjjd*/ fhjgd";
let regex = /($?w*$?)([w d.-]*$?[w d.-]**/)/gm;

result = regex.exec(str).slice(1);

if (result[0].startsWith('$')) {
  result = result[1]

} else {
  result = result[0]   result[1]
}

console.log(result);
  

Комментарии:

1. Не соответствует a $ b */ , a $$ b */ или a $$ b $ c */ правильно.

2. По-прежнему не выполняется для a $ b */ , хотя два других случая, о которых я упоминал ранее, были исправлены.

3. Это также не удается для примера, с которым OP специально обратился за помощью ( xxx. 123 yyy.234 */zzz.567 )

4. Хорошо, я работаю над a $ b */ . Но @ikegami дело в том, что OP специально обратился за помощью. работает. Использую rubular для проверки моего регулярного выражения.

5. Я поместил ваш точный код в консоль Firefox (завернутый в (function(){ ... })() , чтобы я мог запускать несколько тестов). Может быть, вы имели в виду печатать [0] вместо [1] ? Но если вы это сделаете, он сломается a $$ b */ и a $$ b $ c */ .