Estou escrevendo um script de shell para converter algumas páginas do DokuWiki para o formato MediaWiki e vice-versa . Estou tendo alguns problemas com notas de rodapé.
Existe um plugin para o DokuWiki que adiciona recursos estendidos à marcação básica de notas de rodapé do DokuWiki. Uma delas é a capacidade de adicionar um nome a uma nota e reutilizá-la posteriormente. Por exemplo:
DokuWiki | MediaWiki |
---|---|
[(FOO>This is a footnote.)] |
<ref name="FOO">This is a footnote.</ref> |
[(BAR>Another note in the same paragraph.)] |
<ref name="BAR">Another note in the same paragraph.</ref> |
Com sed é fácil encontrar e substituir. Este é o comando do meu script relacionado às notas de rodapé com "nomes de notas":
sed -ri 's@\[\(.*>@<ref name=\"XXX\">@g' dokuwiki-page.txt
sed -ri 's@\)\]@<\/ref>@g' dokuwiki-page.txt
Mas, claro, não preserva os nomes, apenas aplica o novo nome genérico da nota "XXX" a todas as notas que possuem um nome. Então, no meu exemplo acima, o resultado será:
DokuWiki | MediaWiki |
---|---|
[(FOO>This is a footnote.)] |
<ref name="XXX">This is a footnote.</ref> |
[(BAR>Another note in the same paragraph.)] |
<ref name="XXX">Another note in the same paragraph.</ref> |
Preciso de ajuda para preservar o nome da nota (FOO e BAR no exemplo). Aceito outras soluções além de apenas sed .
ANOTAÇÕES IMPORTANTES:
- A frase da nota de rodapé pode aparecer no meio de um parágrafo, e mais de uma referência com nome de nota de rodapé pode aparecer no mesmo parágrafo, mas com um nome diferente. (parágrafo também conhecido como "linhas muito longas" do Unix)
- Não consigo dividir o comando para substituir
[(
em um primeiro comando e>
depois em um segundo comando porque a marcação do MediaWiki faz uso de muitas tags html (cheias de<
e>
). Uma etiqueta pode ser substituída incorretamente. - Existem alguns
[(...)]
sem>
dentro. Como em em[(This is a nameless note.)]
oposição a[(My_Note_Name>This is a named note.)]
.
Esse tipo de coisa é muito mais fácil com
perl
cujas regexps possuem operadores de repetição não gananciosos:Observe que
-i
e-r
são opções não padrãosed
.-i
na verdade, foi copiadoperl
por algumas implementações, embora de maneira incompatível entre si.perl
, ao contrário de váriassed
implementações, também não tem limite no tamanho das linhas, pode lidar com caracteres NUL e, por padrão, trata a entrada em bytes, portanto, não tem problemas com entradas que não podem ser decodificadas como texto na localidade do usuário.Se sua entrada puder ter alguma
[(...)]
que não contenha>
s, você precisará adaptar o regexp. Se as tags de referência contiverem apenasw
caracteres ord (alnums ASCII e sublinhados), então poderia ser apenas:Outra abordagem é encontrar todos
[(...)]
e fazer as substituições em uma etapa separada:Isso também permitiria alterar as notas sem nome para
<ref>nameless</ref>
:Ou usar operadores de antecipação negativos para garantir que as coisas que correspondem dentro de
[(...)]
não incluam)]
:Maneira SED definitiva:
Encontrei uma solução usando grupos sed e regex.
Explicação:
[(
+letters and numbers in any quantity
+>
letters and numbers in any quantity
foram agrupados usando:([[:alnum:]]*)
, para que eu possa referenciar exatamente o mesmo grupo usando\1
. É como armazená-lo em uma variável..*
em vez de([[:alnum:]]*)
porque inclui other>
. Portanto, se houver outras notas de rodapé nomeadas no mesmo parágrafo (também conhecidas como linhas muito longas), a regex incluirá tudo, desde a primeira nota de rodapé até o final da segunda nota de rodapé. Uma bagunça!<ref name="
+letters and numbers in any quantity
+">
.\1
(que representa([[:alnum:]]*)
) para segurá-lo enquanto substituía o que estava ao seu redor.Sugestão de leitura: