Хобрук: Ваш путь к мастерству в программировании

Регулярные выражения Ruby 1.9.3 с gsub: ошибки или особенности?

Возьмите этот фрагмент кода, который должен заменить тег href на его URL:

irb> s='<p><a href="http://localhost/activate/57f7e805827f" style="color:#F19300;font-weight:bold">Click here!</a></p>'
irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/, "#{$1}")
=> "<p></p>"

Это регулярное выражение не работает (URL не найден). Затем я избегаю символа < в регулярном выражении, и это работает:

irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^\<]*)<\/a>/, "#{$1}")
=> "<p>http://localhost/activate/57f7e805827f</p>"

1: Согласно проверкам RubyMine, в этом побеге нет необходимости. Это верно? Если да, то почему побег > тоже не нужен?

2: Затем в том же сеансе IRB с той же строкой исходное регулярное выражение неожиданно работает:

irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/, "#{$1}")
=> "<p>http://localhost/activate/57f7e805827f</p>"

Это потому, что переменная $1 не очищается при повторном вызове gsub? Если да, то это преднамеренное поведение или это ошибка регулярного выражения Ruby?

3: когда я изменяю строку и повторно выполняю ту же команду, $1 изменится только после двойного вызова gsub для измененной строки:

irb> s='<p><a href="http://localhost/activate/xxxxyyy" style="color:#F19300;font-weight:bold">Click here!</a></p>'
=> "<p><a href=\"http://localhost/activate/xxxxyyy\" style=\"color:#F19300;font-weight:bold\">Click here!</a></p>"
irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^\<]*)<\/a>/, "#{$1}")
=> "<p>http://localhost/activate/57f7e805827f</p>"
irb> s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^\<]*)<\/a>/, "#{$1}")
=> "<p>http://localhost/activate/xxxxyyy</p>"

Это намеренно? Если да, то какая логика стоит за этим?

4: В качестве замены символа в некоторых учебниках предлагается использовать "#{$n}", в других — '\n'. С вариантом с обратной косой чертой описанные выше проблемы не возникают. Почему - в чем разница между ними?

Благодарю вас!

28.10.2012

Ответы:


1

$1 содержит первый захват последнего совпадения. В вашем примере он оценивается до сопоставления (фактически даже до вызова gsub), поэтому значение $1 фиксируется равным nil (поскольку вы еще ничего не сопоставили). Таким образом, вы всегда получаете первый захват предыдущего совпадения, вам даже не нужно менять исходное регулярное выражение, чтобы получить ожидаемый результат во второй раз:

s='<p><a href="http://localhost/activate/57f7e805827f" style="color:#F19300;font-weight:bold">Click here!</a></p>'

s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/, "#{$1}")
# => "<p></p>"

s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/, "#{$1}")
# => "<p>http://localhost/activate/57f7e805827f</p>"

Однако вы можете передать блок gsub, который оценивается после сопоставления, т.е. грамм.

s.gsub(/<a href="([^ '"]*)"([^>]*)?>([^<]*)<\/a>/){ $1 }
# => "<p>http://localhost/activate/57f7e805827f</p>"

Таким образом, $1 ведет себя так, как вы ожидаете. Мне нравится всегда использовать именованные захваты, поэтому мне не нужно отслеживать числа, когда я добавляю захват:

s.gsub(/<a href="(?<href>([^ '"]*))"([^>]*)?>([^<]*)<\/a>/){ $~[:href] }
# => "<p>http://localhost/activate/57f7e805827f</p>"
28.10.2012
  • Спасибо, это имеет смысл. 29.10.2012
  • Новые материалы

    Как я могу подписаться на тему изображений в ROS Matlab и получить изображение RGB?
    Привет, Пожалуйста, как я могу извлечь изображение из сообщения ROS Image, за которым следует imshow? Я уже подписался на правильную тему, но message.getData() дает мне объект..

    Понимание СТРУКТУРЫ ДАННЫХ И АЛГОРИТМА.
    Что такое структуры данных и алгоритмы? Термин «структура данных» используется для описания того, как данные хранятся, а алгоритм используется для описания того, как данные сжимаются. И данные, и..

    Как интегрировать модель машинного обучения на ios с помощью CoreMl
    С выпуском новых функций, таких как CoreML, которые упростили преобразование модели машинного обучения в модель coreML. Доступная модель машинного обучения, которую можно преобразовать в модель..

    Создание успешной организации по науке о данных
    "Рабочие часы" Создание успешной организации по науке о данных Как создать эффективную группу по анализу данных! Введение Это обзорная статья о том, как создать эффективную группу по..

    Технологии и проблемы будущей работы
    Изучение преимуществ и недостатков технологий в образовании В быстро меняющемся мире технологии являются решающим фактором в формировании будущего работы. Многие отрасли уже были..

    Игорь Минар из Google приедет на #ReactiveConf2017
    Мы рады сообщить еще одну замечательную новость: один из самых востребованных спикеров приезжает в Братиславу на ReactiveConf 2017 ! Возможно, нет двух других кланов разработчиков с более..

    Я собираюсь научить вас Python шаг за шагом
    Привет, уважаемый энтузиаст Python! 👋 Готовы погрузиться в мир Python? Сегодня я приготовил для вас кое-что интересное, что сделает ваше путешествие более приятным, чем шарик мороженого в..