通过 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\&B=2
但实际上,我在寻找类似的东西:
https://example.com/hello-world/?A=1&B=2
想法是使用反斜杠转义字符 \&
以便它被忽略。最初,我尝试将它直接放入 -o "\&" \
而不是 -o "$ampersand" \
并在这种情况下删除 ampersand=$(echo '\&')
。结果还是一样。
本质上,通过删除反斜杠它仍然输出:
https://example.com/hello-world/?A=1&B=2
只是去掉了&
后面的\
为什么?
我确定缺少一些基本的东西。
如您所见,反斜杠转义不是这里的解决方案。我可以想到两个可能的选择:
提取 href(可能不需要使用 both xmllint
和 xmlstarlet
来执行此操作),然后只需使用标准文本处理工具如sed
添加开始和结束:
sed 's,^,https://example.com/,; s,$,/?A=1\&B=2,'
或者,将您当前得到的输出通过管道传输到 xmlstarlet unesc
,这会将 &
更改为 &
。
抱歉,我无法重现您的结果,但为什么不进行替换呢?只需通过
过滤您的结果
sed 's/\&/\&/g'
将其添加到您的管道中。它应该取代所有 &到 &.
&
是在 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
这是一项非常烦人但更简单的任务。根据这个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\&B=2
但实际上,我在寻找类似的东西:
https://example.com/hello-world/?A=1&B=2
想法是使用反斜杠转义字符 \&
以便它被忽略。最初,我尝试将它直接放入 -o "\&" \
而不是 -o "$ampersand" \
并在这种情况下删除 ampersand=$(echo '\&')
。结果还是一样。
本质上,通过删除反斜杠它仍然输出:
https://example.com/hello-world/?A=1&B=2
只是去掉了&
后面的\
为什么?
我确定缺少一些基本的东西。
如您所见,反斜杠转义不是这里的解决方案。我可以想到两个可能的选择:
提取 href(可能不需要使用 both xmllint
和 xmlstarlet
来执行此操作),然后只需使用标准文本处理工具如sed
添加开始和结束:
sed 's,^,https://example.com/,; s,$,/?A=1\&B=2,'
或者,将您当前得到的输出通过管道传输到 xmlstarlet unesc
,这会将 &
更改为 &
。
抱歉,我无法重现您的结果,但为什么不进行替换呢?只需通过
过滤您的结果sed 's/\&/\&/g'
将其添加到您的管道中。它应该取代所有 &到 &.
&
是在 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