Script Sed (ou outro) para substituir um caractere dentro do grupo de captura

Script Sed (ou outro) para substituir um caractere dentro do grupo de captura

Estou tentando converter a marcação Pandoc em marcação wiki do Confluence, estou usandomarkdown2confluênciapara fazer a maior parte do trabalho. Isso funciona muito bem, exceto quando estou falando sobre CSS e FreeMarker que usam {& }no código enquanto o Confluence usa {{& }}para marcar o início/fim do bloco de código. Portanto, preciso corresponder a um padrão incluído em {{...}}.

Se eu conhecesse (mais) Ruby, poderia consertá-lo lá, mas sou um cara da velha escola do Unix, então pensei em awk ou sed.

Então cheguei até:

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

que leva:

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 {{*}}.

e produz:

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 {{"*"}}.

Mas o que eu preciso é:

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 {{*}}.

Também precisa lidar com {{${type.name}}}o que deve se tornar {{$\{type.name\}}}.

Existem dois problemas

  1. Preciso substituir {por \{em vez de usar aspas, então preciso modificar \1de alguma forma.
  2. A aparência desagradável {{}}}(que deveria acontecer {{\}}}não sai bem, não importa o quanto eu tente encerrar a correspondência de padrões.

Responder1

O seguinte comando sed parece funcionar:

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

Explicação:

  1. {{\([^*[a-z][^}]*\)}}finds {{stuff}}, exceto quando stuffcomeça com *ou [ou uma letra minúscula.
  2. Substitua por {{\stuff}}.
  3. Então {{\\${\([^}]*\)}}}encontra {{\${junk}}}.
  4. E substitui por {{$\{junk\}}}.

Editar: Uma solução alternativa, após esclarecimento do OP, poderia ser esta:

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

Como todos sabemos, o sed não pode fazer análise recursiva, mas isso deve funcionar na maioria dos casos simples.

Explicação:

  1. \({{[^}]*\){\([^}]*}}\)encontra {{foo{bar}}, onde fooe barnão contém }.
  2. E substitui por {{foo\{bar}}. (A nota {{xxx{yyy}}}foi tratada corretamente.)
  3. Então \({{[^}]*\)}}}encontra {{baz}}}, onde baznão contém }.
  4. E substitui por {{baz\}}}.

foo, bar, e bazpodem estar vazios, por exemplo, {{}}}são convertidos em {{\}}}, conforme necessário.

informação relacionada