Page 281 - Браун Э. - Изучаем JavaScript. Руководство по созданию современных веб-сайтов - 2017
P. 281

Есть некий НТМL-код, и вы хотите заменить в  нем,  например, дескриптор < i >
       дескриптором <strong>. Вот наша первая попытка.

       const  input  =  "Regex  pros  know  the  difference  between\n"  +
           "<i>greedy</i>  and  <i>lazy</i>  matching . " ;
                                             >
       input . replace ( /<i> ( . * )   < \ / i > / i g ,    ' < strong $ 1   / <   strong> ' ) ;
          Часть $ 1   в строке замены будет заменена содержимым группы  ( . * )  в регулярном
       выражении (подробности - далее).
          Давайте опробуем это. Вы получите следующий неутешительный результат.
       "Regex  pros  know  the  dif ference  between
       <strong>greedy</i>  and  <i>lazy</strong>  matching . "
          Чтобы понять происходящее здесь, давайте вспомним, как функционирует обра­
       ботчик регулярного выражения: он перерабатывает входные данные, пока не най­
       дет соответствие, а затем снова продолжает переработку. Стандартно он делает это
       жадным способом: находит первое  i > , а затем говорит "Я не остановлюсь, пока не
                                       <
                                                              <
       увижу самый последний  / i > . Поскольку есть два экземпляра  / i > , он закончит свою
                             <
       работу на втором, а не на первом.
          Есть несколько  способов  исправить  этот пример, но поскольку мы обсуждаем
       различие между жадным и  ленивым распознаваниями, давайте создадим ленивый
                               *
       метасимвол повторения (  ) . Для этого нужно просто поместить после него вопро­
       сительный знак.
                    (
                          *
       input . replace  / <i> ( .  ? )   < \ /  i>/ ig,  ' < strong $ 1   </ strong> ' ) ;
                                              >
          Регулярное выражение - точно то же, за исключением вопросительного знака пос­
       ле метасимвола *. Теперь процессор регулярного выражения рассматривает его так: "я
       остановлюсь, как только увижу первый < / i »:  Таким образом, он лениво прекращает
       анализ, когда встречает первый  / i > , несмотря на то что подобное соответствие может
                                   <
       встретиться далее еще не один раз. Хотя со словом ленивый (lazy) обычно ассоциируется
       нечто отрицательное, это поведение - именно то, что нам нужно в данном случае.
          Все метасимволы повторения ( * , +, ?,  { n } ,   { n , }  и  { n , m } )   можно сопроводить во­
       просительным знаком, чтобы сделать их ленивыми (хотя на практике я использовал
       его только для * и + ).


       Обратные ссыпки

          Группировка  обеспечивает  еще  одну  возможность  - обратные  ссылки
       (backreference). В моей практике это одно из наименее используемых средств регу­
       лярного  выражения,  но есть один случай, когда без него не обойтись. Прежде чем
       рассмотреть действительно полезный пример, давайте сначала рассмотрим глупый.
          Предположим, что вы хотите распознавать названия поп-групп согласно шаблону
       ХУУХ (держу пари,  вы можете вспомнить названия реальных поп -групп,  которые



       284      Глава 1 7 .   Регулярные выражения
   276   277   278   279   280   281   282   283   284   285   286