我正在编写一个 shell 脚本来将一些 DokuWiki 页面转换为 MediaWiki 格式,反之亦然。我在脚注方面遇到了一些麻烦。
DokuWiki 有一个插件,可以为 DokuWiki 的基本脚注标记添加扩展功能。其中之一是能够向笔记添加名称并在以后重复使用。例如:
多库维基 | 媒体维基 |
---|---|
[(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> |
使用sed可以轻松查找和替换。这是我的脚本与带有“注释名称”的脚注相关的命令:
sed -ri 's@\[\(.*>@<ref name=\"XXX\">@g' dokuwiki-page.txt
sed -ri 's@\)\]@<\/ref>@g' dokuwiki-page.txt
但是,当然,它不会保留名称,它只是将新的通用注释名称“XXX”应用于所有具有名称的注释。因此,在我上面的示例中,结果将是:
多库维基 | 媒体维基 |
---|---|
[(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> |
我需要帮助来保留注释名称(示例中的 FOO 和 BAR)。我确实接受除sed之外的其他解决方案。
重要笔记:
- 脚注句子可以出现在段落的中间,并且多个带有脚注名称的引用可以出现在同一段落中但具有不同的名称。(又名 Unix 的“非常长的行”的段落)
- 我无法拆分命令以
[(
在第一个命令中替换,>
然后在第二个命令中替换,因为 MediaWiki 标记使用了太多的 html 标签(充满 和<
)>
。一个标签可能会被不正确地替换。 - 有一些
[(...)]
没有>
里面的。就像在 中[(This is a nameless note.)]
而不是[(My_Note_Name>This is a named note.)]
.
perl
使用具有非贪婪重复运算符的正则表达式,这种事情要容易得多:请注意,
-i
和-r
是非标准sed
选项。-i
实际上是perl
由一些实现复制的,尽管彼此之间的方式不兼容。perl
与几种sed
实现相反,它对行的大小也没有限制,可以处理 NUL 字符,并且默认情况下按字节处理输入,因此不存在无法在用户区域设置中解码为文本的输入问题。如果您的输入可能有一些
[(...)]
不包含>
s,那么您需要调整正则表达式。如果引用标签仅包含w
ord 字符(ASCII 数字和下划线),那么它可能只是:另一种方法是找到所有
[(...)]
并在其中进行替换作为单独的步骤:这也将允许使用将无名注释更改为
<ref>nameless</ref>
:[(...)]
或者使用负向前看运算符来确保在不包含的内容中匹配)]
:最终的SED方式:
我通过使用sed和正则表达式组找到了解决方案。
解释:
[(
+letters and numbers in any quantity
+的行>
letters and numbers in any quantity
使用: 进行分组([[:alnum:]]*)
,所以我可以使用 引用完全相同的组\1
。这就像将其存储在变量中。.*
代替,([[:alnum:]]*)
因为它包括其他>
. 因此,如果同一段落中有任何其他命名脚注(也称为非常长的行),则正则表达式将包含从第一个脚注到第二个脚注末尾的所有内容。一团糟!<ref name="
+letters and numbers in any quantity
+">
。\1
(代表([[:alnum:]]*)
)来握住它,同时替换它周围的东西。阅读建议: