使用 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

相关内容