Sed
如果前一行與模式不匹配,則使用 sed 在多行之間添加文本
我正在努力
<dl>
使用 sed 在定義列表周圍添加標籤,也許有一種更簡單的方法可以做到這一點(我很想知道)。我想在文件中搜尋包含 a 的任何行
<dt>
,但僅在前一行不包含or<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
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。每個開始標籤都需要有一個結束標籤。
這可能
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>