Отключить амперсанд (&) через XMLStarlet - Bugging & amp;

Это довольно раздражающая, но гораздо более простая задача. Согласно этому руководству, я написал это:

#!/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 \

Я успешно извлекаю каждую ссылку из таблицы, и все соединяется правильно, однако вместо того, чтобы воспроизводить амперсанд, поскольку & я получаю это в конце каждой ссылки:

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; устранен.

Зачем?

Я уверен, что это что-то базовое, чего не хватает.

3 ответа

Решение

Извините, я не могу воспроизвести ваш результат, но почему бы не сделать замены? Просто отфильтруйте свои результаты через

sed 's/\\&amp;/\&/g'

добавь это в свою трубу. Он должен заменить все & amp; к &.

&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

Как вы уже видели, экранирование от обратной косой черты здесь не является решением. Я могу придумать два возможных варианта:

Извлеките ссылки (вероятно, не нужно использовать оба xmllint а также xmlstarlet для этого), а затем просто используйте стандартный инструмент для обработки текста, такой как sed добавить начало и конец:

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

В качестве альтернативы, направьте вывод того, что вы в настоящее время получили xmlstarlet unesc, который изменится &amp; в &,

Другие вопросы по тегам