我正在努力使用<dl>
sed 在定义列表周围添加标签,也许有一种更简单的方法来做到这一点(我很想知道)。
我想在文件中搜索包含 a 的任何行<dt>
,但仅当上一行包含时才匹配不是包含<dt>
或<dd>
.当找到匹配项时,插入<dl>
.
到目前为止我的尝试(根本不匹配):
sed '/^((?!<dt>).)*$/ {
N
/<dt>/ {
s/<dt>/<dl><dt>/
}
}' file
还有文件
# TODO #
* Set up mail transfer agent
* Reconfigure timezone
```bash
dpkg-reconfigure tzdata
```
# Hardware #
<dt>RAM</dt>
<dd>2GB</dd>
# Partitions #
<dt>`/dev/sda1`</dt>
<dd>/boot</dd>
<dt>`/dev/sda2`</dt>
<dd>/</dd>
所有这一切的目的是编写一个解析器,将 moinmoin wiki 标记转换为 Markdown,以便移植到新的 wiki 引擎。目前定义列表是按照以下规则制定的:
sed -i 's/^ \(.*\):: \(.*\)$/ <dt>\1<\/dt>\n <dd>\2<\/dd>/' file
我希望输出看起来像这样:
# TODO #
* Set up mail transfer agent
* Reconfigure timezone
```bash
dpkg-reconfigure tzdata
```
# Hardware #
<dl>
<dt>RAM</dt>
<dd>2GB</dd>
</dl>
# Partitions #
<dl>
<dt>`/dev/sda1`</dt>
<dd>/boot</dd>
<dt>`/dev/sda2`</dt>
<dd>/</dd>
</dl>
请注意,我希望尽可能有效的 html。每个开始标签都需要有一个结束标签。
答案1
这可能超出sed
您的预期,但我认为这是实现您想要的最好方法sed
。
这个脚本:
如果该行前面没有其他 、、或 ,则在
<dl>
包含 的每行之前插入一行。<dt>
<dt>
<dd>
<dl>
</dl>
如果包含 的行后面的行不包含<dd>
,则在包含 的每行之后追加一行。<dd>
<dd>
该sed
脚本使用sed
hold
空格来记住前一行,以便可以<d[tdl]>
在插入标签之前检查标签<dl>
。它还使用相对寻址ADDR,+N
来允许添加结束</dl>
标记。需要一种特殊情况来检测 a 是否<dd>
位于文件的最后一行并且需要附加</dl>
.测试(t
和T
)和分支(b
)被广泛用于实现逻辑。
#!/bin/sh
sed '
/<dt>/ {
x # exchange pattern and hold space
s/<d[tdl]>// # subsitutue, just testing for pattern
g # copy hold space back, overwriting pattern space
t end # branch to :end if previous subsitution successful
i \
<dl>
}
$ {
/<dd>/ ! b end # if <dd> on last line, append </dl>
a \
</dl>
}
/<dd>/,+1 { # on each line containing <dd> and the line after
/<dd>/ b end # if does not contain <dd>, insert </dl>
i \
</dl>
}
:end
h # copy pattern space to hold space for next round
' "$@"
该脚本将示例数据修改为如下所示:
[...]
# Hardware #
<dl>
<dt>RAM</dt>
<dd>2GB</dd>
</dl>
# Partitions #
<dl>
<dt>`/dev/sda1`</dt>
<dd>/boot</dd>
<dt>`/dev/sda2`</dt>
<dd>/</dd>
</dl>