使用 awk 或 sed 刪除 < > 之間的所有內容

使用 awk 或 sed 刪除 < > 之間的所有內容

我的txt檔案中有以下內容:

<ol><li><b><a href="/page1/Mark_Yato" title="Mark Yato">Mark Yato</a> ft. MarkAm &amp; <a href="/page1/Giv%C4%93on" title="Givēon">Givēon</a> - <a href="/page1/Mark_Yato:Thuieo" title="Mark Yato:Thuieo">Thuieo</a> (7)</b></li>
<li><b><a href="/page1/The_Central" title="The Central">The Central</a> - <a href="/page1/The_Central:AHTIOe oie" title="The Central:AHTIOe oie">AHTIOe oie</a> (7)</b></li>
<li><b><a href="/page1/Taa_Too_A" title="Taa Too A">Taa Too A</a> - <a href="/page1/Taa_Too_A:ryhwtyw w" title="Taa Too A:ryhwtyw w">ryhwtyw w</a> (8)</b></li>

並試圖使其輸出如下:

Mark Yato ft. MarkAm & Givēon - Thuieo
The Central - AHTIOe oie
Taa Too A - ryhwtyw w

為了實現這一目標,我想我會嘗試刪除「<」、「>」以及它們之間的所有內容,這樣就只剩下我想要取得的清單。

我已經嘗試過以下 sed 命令:

sed 's/<[^()]*>//g'

但這僅輸出以下內容:

(7)
(7)
(8)

我做錯了什麼以及如何修復 sed 命令或將其轉換為 awk(如果它更適合)?

答案1

用正規表示式解析標記是出了名的問題

雖然範例資料不是問題,但尖括號可能會出現在標籤屬性、註解和可能的其他位置中,從而使匹配 from 的正規表示式變得<>可靠。

您應該求助於實作標記解析器的工具。

例如,使用潘多克(版本> = 2.8)與您的範例資料(不添加缺少的</ol>標籤):

$ pandoc -f html -t plain file 
Mark Yato ft. MarkAm & Givēon - Thuieo (7)

The Central - AHTIOe oie (7)

Taa Too A - ryhwtyw w (8)

然後,您可以輕鬆地將此輸出作為常規文字進行後處理,以刪除空白行和其他不需要的部分:

$ pandoc -f html -t plain file |
  sed -e '/^$/d' -e 's/[[:blank:]]*([[:digit:]]*)$//'
Mark Yato ft. MarkAm & Givēon - Thuieo
The Central - AHTIOe oie
Taa Too A - ryhwtyw w

請注意,在 2.8 版本之前,pandoc用於在生成格式輸出時將任何強調文字轉換為全部大寫plain。清單項目中的標籤<b>將觸發此行為(更多資訊請參見變更日誌或相關的犯罪在 GitHub 上)。

根據您的實際輸入數據,解決方法可能是明確使用markdownas的輸入格式:pandoc

pandoc -f markdown -t plain file

或隱含地考慮到它pandoc自動預設為 ( pandoc -t plain file)。

答案2

你就快到了 - 正規表示式匹配是“貪婪的”,所以你需要告訴模式,>模式內不允許有結束字元。換句話說,[^()]*模式內的部分將「貪婪地」匹配盡可能多的文字。如果您不告訴模式>從模式的這一部分中排除結束語,則正規表示式使用的開始<和結束>不一定是從 HTML 角度來看配對的。

使用這個代替:

sed -e 's/<[^>]*>//g'

這會強制正規表示式刪除每個 HTML 標籤,而不是刪除結尾處以及<中間有和的較大文字區塊。><>

答案3

您可以使用php剝離所有 HTML 標籤並將 HTML 實體轉換回普通字元:

$ <file php -r 'echo htmlspecialchars_decode(strip_tags(file_get_contents("php://stdin")), ENT_HTML5);'
Mark Yato ft. MarkAm & Givēon - Thuieo (7)
The Central - AHTIOe oie (7)
Taa Too A - ryhwtyw w (8)

若要另外刪除空格(空格、製表符),後面跟著一個開頭(,後面跟著一個或多個數字,並)在以 結尾的行處結束sed

$ <file php -r 'echo htmlspecialchars_decode(strip_tags(file_get_contents("php://stdin")), ENT_HTML5);' |
    sed 's/[[:blank:]]*([[:digit:]][[:digit:]]*)$//'
Mark Yato ft. MarkAm & Givēon - Thuieo
The Central - AHTIOe oie
Taa Too A - ryhwtyw w

答案4

使用xmlstarlet

xmlstarlet fo -H file |
xmlstarlet sel -E latin1 -t -v '//li' -nl 2>/dev/null |
xmlstarlet unesc | sed 's/ [^ ]*$//'

這用於xmlstarlet將 HTML 片段轉換為格式良好的 HTML 文件(第一個命令)。然後它提取每個節點的值li(第二個命令)。最後,它解碼任何 HTML 實體(&amp;例如)。最後的sed命令只是刪除每行最後一個空格之後的所有內容(括號中的數字不應成為輸出的一部分)。

問題中給出的文檔的輸出:

Mark Yato ft. MarkAm & Givēon - Thuieo
The Central - AHTIOe oie
Taa Too A - ryhwtyw w

相關內容