通过 XMLStarlet 取消转义符号 (&) - 窃听 &

Unescape the ampersand (&) via XMLStarlet - Bugging &

这是一项非常烦人但更简单的任务。根据这个guide,我这样写:

#!/bin/bash

content=$(wget "https://example.com/" -O -)
ampersand=$(echo '\&')

xmllint --html --xpath '//*[@id="table"]/tbody' - <<<"$content" 2>/dev/null |
    xmlstarlet sel -t \
        -m "/tbody/tr/td" \
            -o "https://example.com" \
            -v "a//@href" \
            -o "/?A=1" \
            -o "$ampersand" \
            -o "B=2" -n \

我成功地从 table 中提取了每个 link 并且所有内容都正确地连接了,但是,而不是将 ampersand 重现为 & 我在每个 link:

的末尾收到这个
https://example.com/hello-world/?A=1\&amp;B=2

但实际上,我在寻找类似的东西:

https://example.com/hello-world/?A=1&B=2

想法是使用反斜杠转义字符 \& 以便它被忽略。最初,我尝试将它直接放入 -o "\&" \ 而不是 -o "$ampersand" \ 并在这种情况下删除 ampersand=$(echo '\&') 。结果还是一样。

本质上,通过删除反斜杠它仍然输出:

https://example.com/hello-world/?A=1&amp;B=2

只是去掉了&amp;后面的\

为什么?

我确定缺少一些基本的东西。

如您所见,反斜杠转义不是这里的解决方案。我可以想到两个可能的选择:

提取 href(可能不需要使用 both xmllintxmlstarlet 来执行此操作),然后只需使用标准文本处理工具如sed添加开始和结束:

sed 's,^,https://example.com/,; s,$,/?A=1\&B=2,'

或者,将您当前得到的输出通过管道传输到 xmlstarlet unesc,这会将 &amp; 更改为 &

抱歉,我无法重现您的结果,但为什么不进行替换呢?只需通过

过滤您的结果
sed 's/\&amp;/\&/g'

将其添加到您的管道中。它应该取代所有 &到 &.

&amp; 是在 XML 文档中打印 & 的正确方法,但是由于您只想要一个普通的 URL,因此您的输出不应该是 XML.因此,您需要通过将 --text-T 传递给 sel 命令来切换到文本模式。

您的示例输入不太有效,因为 example.com 没有任何 table 元素,但这里是一个从 p 元素构建链接的工作示例。

content=$(wget 'https://example.com/' -O -)
xmlstarlet fo --html <<<"$content" |
    xmlstarlet sel -T -t \
        -m '//p[a]' \
            --if 'not(starts-with(a//@href,"http"))' \
              -o 'https://example.com/' \
            --break \
            -v 'a//@href' \
            -o '/?A=1' \
            -o '&' \
            -o 'B=2' -n

输出为

http://www.iana.org/domains/example/?A=1&B=2