Скрипт Sed (или другой) для замены символа в группе захвата

Скрипт Sed (или другой) для замены символа в группе захвата

Я пытаюсь преобразовать разметку Pandoc в вики-разметку Confluence, я используюmarkdown2confluenceдля выполнения основной части работы. Это работает довольно хорошо, за исключением случаев, когда я говорю о CSS и FreeMarker, которые используют {& }в коде, в то время как Confluence использует {{& }}для обозначения начала/конца блока кода. Поэтому мне нужно сопоставить шаблон, заключенный в {{...}}.

Если бы я знал Ruby (больше), я бы, возможно, смог это исправить, но я приверженец Unix старой школы, поэтому я подумал об awk или sed.

Итак, я дошел до того, что:

   sed 's/{{\([^}}]*\)}}/{{"\1"}}/g' tmp.wkd

что занимает:

First we need a way to select a state (or group of states) CSS uses what
is called a selector to choose which elements to apply to, we have been
using one up until now without noticing, it is the {{*}} at the beginning
of our CSS. This is a special selector that means select everything. So
the rule that follows it (the bit between {{{}} and {{}}} apply to every
polygon on the map. But CSS allows us to insert a filter instead by
using {{[...]}} instead of {{*}}.

и производит:

First we need a way to select a state (or group of states) CSS uses what
is called a selector to choose which elements to apply to, we have been
using one up until now without noticing, it is the {{"*"}} at the beginning
of our CSS. This is a special selector that means select everything. So
the rule that follows it (the bit between {{"{"}} and {{""}}} apply to every
polygon on the map. But CSS allows us to insert a filter instead by
using {{"[...]"}} instead of {{"*"}}.

Но мне нужно следующее:

First we need a way to select a state (or group of states) CSS uses what
is called a selector to choose which elements to apply to, we have been
using one up until now without noticing, it is the {{*}} at the beginning
of our CSS. This is a special selector that means select everything. So
the rule that follows it (the bit between {{\{}} and {{\}}} apply to every
polygon on the map. But CSS allows us to insert a filter instead by
using {{[...]}} instead of {{*}}.

Также необходимо обработать {{${type.name}}}то, что должно стать {{$\{type.name\}}}.

Есть две проблемы

  1. Мне нужно заменить {на \{вместо использования кавычек, поэтому мне нужно \1как-то изменить.
  2. Отвратительный вид {{}}}(который должен быть), {{\}}}не получается как надо, как бы я ни пытался завершить сопоставление с образцом.

решение1

Следующая команда sed, похоже, работает:

   sed 's/{{\([^*[a-z][^}]*\)}}/{{\\\1}}/g;s/{{\\${\([^}]*\)}}}/{{$\\{\1\\}}}/g'

Объяснение:

  1. {{\([^*[a-z][^}]*\)}}находит {{stuff}}, за исключением случаев, когда stuffначинается с *или [или строчной буквы.
  2. Замените его на {{\stuff}}.
  3. Затем {{\\${\([^}]*\)}}}находит {{\${junk}}}.
  4. И заменяет его на {{$\{junk\}}}.

Редактировать: Альтернативным решением, после разъяснений от OP, может быть следующее:

   sed 's/\({{[^}]*\){\([^}]*}}\)/\1\\{\2/g;s/\({{[^}]*\)}}}/\1\\}}}/g'

Как мы все знаем, sed не может выполнять рекурсивный анализ, но в большинстве простых случаев это должно сработать.

Объяснение:

  1. \({{[^}]*\){\([^}]*}}\)находит {{foo{bar}}, где fooи barне содержат }.
  2. И заменяет его на {{foo\{bar}}. (Примечание {{xxx{yyy}}}обрабатывается нормально.)
  3. Затем \({{[^}]*\)}}}находит {{baz}}}, где bazне содержит }.
  4. И заменяет его на {{baz\}}}.

foo, bar, и bazможет быть пустым, поэтому, например, {{}}}преобразуется в {{\}}}, при необходимости.

Связанный контент