Руби Регулярные выражения – Совпадение точно N обратных кавычек с точно N обратными кавычками

Вопросы и ответы

Я думаю, что нашел решение для проблемы на GitHub, но это связано с немного сложным RegEx в Ruby. (Я редко работал с Ruby и не назвал бы себя профессионалом в RegEx). Проблема в том, что когда у вас есть, скажем, 5 (все, что больше 3) открывающих обратных кавычек, затем парсер встречает 3 обратные кавычки, он автоматически закроет блок кода. В основном код выглядит следующим образом:

  def escape_liquid_tags_in_codeblock(content)
      # Экранировать блоки кода, кодовые фрагменты и встроенный код
      content.gsub(/[[:space:]]*~{3}.*?~{3}|[[:space:]]*`{3}.*?`{3}|`{2}.+?`{2}|`{1}.+?`{1}/m) do |codeblock|
        codeblock.gsub!("{% endraw %}", "{----% endraw %----}")
        codeblock.gsub!("{% raw %}", "{----% raw %----}")
        if codeblock.match?(/[[:space:]]*`{3}/)
          "\n{% raw %}\n#{codeblock}\n{% endraw %}\n"
        else
          "{% raw %}#{codeblock}{% endraw %}"
        end
      end
    end

Прежде всего, блок кода в Markdown может содержать по крайней мере 3 обратные кавычки (`) или тильды (~), а не обязательно ровно 3. Я верю, что знаю решение этой проблемы, но мне нужно узнать, возможно ли написать что-то вроде этого?

[[:space:]]*`{N}.*?`{N}

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

Я также считаю, что условие if должно быть {3,}, а не {3}. Если кто-то может сказать мне, как иметь regex с N начальными обратными кавычками и N закрывающими обратными кавычками, это было бы здорово. Я также открыт для любых предложений о том, как подойти к этой проблеме.

Я пытался задать это ChatGPT, но он не дал мне правильный RegEx, если это вообще возможно.

Я не знаю Ruby regex, но это решение является корректным согласно https://regex101.com/

Во-первых, я согласен с вашим утверждением “по крайней мере”:

  • Измените {3} на {3,}, чтобы соответствовать по крайней мере 3 символам.

Далее, группы захвата также применяются здесь (в PCRE).

  • Измените …{3,}.*?{3,}… на: …{(3,)}.*?{\1}

Это regex, который я тестирую на сайте, указанном выше:

 [[:space:]]*~{3}.*?~{3}|[[:space:]]*`{(3,)}.*?`{\1}|`{2}.+?`{2}|`{1}.+?`{1}

Обратите внимание, что я изменил это только для варианта с обратными кавычками. Вам нужно сделать то же самое для тильды и изменить \1 на \2 соответственно. Согласно подсветке, это работает отлично. Посмотрите:

скриншот regex101.com

Это работает для PCRE (Perl, PHP), Javascript, Python и .NET; но не работает для Golang, Java 8 и Rust, которые не поддерживают группы захвата, помещенные в это место. Обратите внимание, что последние несоответствующие обратные кавычки не подсвечиваются.

Ответ

Ваша задача состоит в том, чтобы создать регулярное выражение Ruby для поиска блока кода, который начинается и заканчивается одинаковым количеством обратных кавычек (backticks). При этом можно использовать N количества обратных кавычек, где N больше или равно 3.

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

Решение

Для того чтобы создать регулярное выражение, удовлетворяющее этим условиям, мы можем воспользоваться следующим подходом:

  1. Подходящая конструкция: Для поиска минимум трёх обратных кавычек, которые будут одинаковыми как в начале, так и в конце, мы используем конструкцию с захватывающей группой.
  2. Регулярное выражение: Вот окончательное выражение, которое вы можете использовать:
content.gsub(/([`~]{3,})\s*(.*?)\s*\1/m) do |codeblock|
  codeblock.gsub!("{% endraw %}", "{----% endraw %----}")
  codeblock.gsub!("{% raw %}", "{----% raw %----}")

  "\n{% raw %}\n#{codeblock}\n{% endraw %}\n"
end

Объяснение регулярного выражения

  • ([~]{3,}): Эта часть ищет последовательность из не менее чем трёх символов ( или ~) и помещает её в захватывающую группу. Мы используем круглые скобки, чтобы зафиксировать эту последовательность для дальнейшего использования.
  • \s*: Эта часть ищет любое количество пробелов (включая ноль) между открывающей и закрывающей последовательностью.
  • (.*?): Эта часть находит любое содержимое между открывающей и закрывающей последовательностями. Знак вопроса делает поиск «ленивым» (он пытается минимизировать количество совпадений).
  • \1: Здесь происходит проверка, чтобы закрывающая последовательность соответствовала той же самой последовательности, что и открывающая (что захвачено в первой группе).

Пример использования

Пример того, как можно использовать это регулярное выражение в методе:

def escape_liquid_tags_in_codeblock(content)
  content.gsub(/([`~]{3,})\s*(.*?)\s*\1/m) do |codeblock|
    codeblock.gsub!("{% endraw %}", "{----% endraw %----}")
    codeblock.gsub!("{% raw %}", "{----% raw %----}")

    "\n{% raw %}\n#{codeblock}\n{% endraw %}\n"
  end
end

Заключение

Это регулярное выражение работает как для обратных кавычек, так и для тильд, так как вы имеете возможность добавлять их в выражение. Обратите внимание, что группы повторов также могут быть применены для каждого варианта (тильда и кавычки). Убедитесь, что вы правильно обрабатываете и другие типы кода в вашем методе. Надеюсь, это поможет вам разобраться с вашей задачей!

Оцените материал
Добавить комментарий

Капча загружается...