Sed

如果前一行與模式不匹配,則使用 sed 在多行之間添加文本

  • December 13, 2015

我正在努力<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

這個腳本:

  • &lt;dl&gt;在每行之前插入一行&lt;dt&gt;,如果沒有其他&lt;dt&gt;,則在該行之前插入一個&lt;dd&gt;&lt;dl&gt;
  • 如果包含 的行後面的行不&lt;/dl&gt;包含 ,則在包含 的每一行之後追加一行。&lt;dd&gt;``&lt;dd&gt;``&lt;dd&gt;

sed腳本使用sed hold空間來記住前一行,以便&lt;d[tdl]&gt;在插入標籤之前檢查&lt;dl&gt;標籤。它還使用相對定址ADDR,+N來允許添加結束&lt;/dl&gt;標記。需要一種特殊情況來檢測 a&lt;dd&gt;是否在文件的最後一行並且需要附加一個&lt;/dl&gt;. 測試(tT)和分支(b)被廣泛用於實現邏輯。

#!/bin/sh

sed '
   /&lt;dt&gt;/ {
       x                  # exchange pattern and hold space
       s/&lt;d[tdl]&gt;//       # subsitutue, just testing for pattern
       g                  # copy hold space back, overwriting pattern space
       t end              # branch to :end if previous subsitution successful
       i \
&lt;dl&gt;
   }

   $ {
       /&lt;dd&gt;/ ! b end     # if &lt;dd&gt; on last line, append &lt;/dl&gt;
       a \
&lt;/dl&gt;
   }

   /&lt;dd&gt;/,+1 {            # on each line containing &lt;dd&gt; and the line after
       /&lt;dd&gt;/ b end       # if does not contain &lt;dd&gt;, insert &lt;/dl&gt;
       i \
&lt;/dl&gt;
   }

:end
   h                      # copy pattern space to hold space for next round

' "$@"

此腳本將範例數據修改為如下所示:

[...]

# Hardware #
&lt;dl&gt;
 &lt;dt&gt;RAM&lt;/dt&gt;
 &lt;dd&gt;2GB&lt;/dd&gt;
&lt;/dl&gt;

# Partitions #

&lt;dl&gt;
&lt;dt&gt;`/dev/sda1`&lt;/dt&gt;
&lt;dd&gt;/boot&lt;/dd&gt;
&lt;dt&gt;`/dev/sda2`&lt;/dt&gt;
&lt;dd&gt;/&lt;/dd&gt;
&lt;/dl&gt;

引用自:https://unix.stackexchange.com/questions/248020