Tente algo como:
declate -a url_array
url_array=('echo $XML | grep -o "http.*zip" | tr '\n' ' '')
Estou tentando baixar alguns arquivos de um serviço. Os arquivos são encontrados em um arquivo XML. O arquivo XML pode ter um único arquivo ou vários arquivos para download. No entanto, agora eu tenho um problema com o meu script. Eu não sei como dividir a string de XMLLINT em array para que eu possa fazer o download de cada arquivo individualmente.
Eu preciso dividir a string em várias variáveis e, em seguida, fazer o download de cada arquivo da string de URL.
No entanto, o arquivo 201701_1 não se repete e, portanto, eu os baixo usando o curl sem problemas. Mas os arquivos coverage.zip se repetem e são sobrescritos por curl. Eu faço: Então eu faço o curl para baixar arquivos individuais.
curl -O -b cookie $URL
No momento, meu script é o seguinte:
while read edition; do XML="<?xml version=\"1.0\"
encoding=\"UTF-8\"?> <download-area> <files>
<file>
<url>https://google.com/411/201701_01_01.zip</url>
</file>
<file>
<url>https://google.com/411/201701_01_02.zip</url>
</file> </files> </download-area>
"
URL=$(echo $XML | xmllint --xpath \
"/*[name()='download-area']/*[name()='files']/*[name()='file']/*[name()='url']/text()" -)
echo "URL:: " $URL
done < $LATEST_EDITION
LATEST_EDITION é simplesmente um arquivo com linhas.
Minha pergunta é: Como posso dividir VAR_1 e VAR_2 em várias URLs para que eu possa baixá-las individualmente? Como posso evitar que coverage.zip seja sobrescrito?
Tente algo como:
declate -a url_array
url_array=('echo $XML | grep -o "http.*zip" | tr '\n' ' '')
xmllint
não é uma ótima ferramenta para cortar e separar XML. Para resolver seus dois problemas (analisando XML e garantindo URLs exclusivas, eu acho?) De forma robusta usando bash
e xmlstarlet
:
#!/bin/bash
XML='<?xml version="1.0" encoding="UTF-8"?>
<download-area>
<files>
<file>
<url>https://google.com/411/201701_01_01.zip</url>
</file>
<file>
<url>https://google.com/411/201701_01_02.zip</url>
</file>
</files>
</download-area>'
# IFS=$'\n' ## required if URLs contains spaces
urls=( $(xml select -t -m "/download-area/files/file" -v url -nl <<< $XML ) )
declare -A unique # associative array
for uu in ${urls[*]}; do let unique[$uu]++; done
for uu in "${!unique[@]}"; do
printf "URL is %s\n" ${uu}
done
Isso usa o modo xmlstarlet
in select
, com um modelo ( -t
) que corresponde ( -m
) a um caminho x a partir do qual seleciona o valor ( -v
) do nó url
e adiciona uma nova linha ( -nl
) depois de cada uma. (xmlstarlet é ainda mais flexível do que isso, você pode usar -v
várias vezes e -o
para adicionar texto arbitrário sempre que necessário.)
Isso também usa o redirecionamento <<<
, que salva echo
/ pipe.
As URLs são armazenadas em uma matriz indexada normal urls
. Em seguida, faça um loop sobre a matriz para armazenar as URLs como as chaves em uma matriz associativa - isso resolve o problema de unicidade (e a contagem de ocorrências é mantida como o valor de cada entrada).
Se você não estiver familiarizado com os arrays associativos de bash, o segundo loop precisa de alguma explicação adicional. A expressão "${unique[@]}"
expande todos os valores de uma matriz, isso usa "${!unique[@]}"
, que em vez expande todos os índices de uma matriz, isso deve fazer sentido se você esvaziar dados da matriz com declare -p unique
:
declare -A unique=([https://google.com/411/201701_01_01.zip]="1"
[https://google.com/411/201701_01_02.zip]="1" )
Você pode até fazer tudo isso em um único loop, embora seja um pouco difícil de entender, talvez:
while read line; do
[[ -n "$line" ]] && let unique[$line]++
done < <(xml sel -t -m "/download-area/files/file" -v url -nl <<< $XML)
O XMLstarlet pode ser instalado como xml
ou xmlstarlet
xmllint
é bastante inútil para extrair informações de documentos XML. Você pode considerar xmlstarlet
ou xml_grep
(da perl
's XML :: Twig) ou xml2
.
Com xmllint
, você ainda pode extrair uma string de cada vez com:
VAR1=$(printf '%s\n' "$XML" |
xmllint --xpath '/download-area/files/file[1]/url/text()' -)
VAR2=$(printf '%s\n' "$XML" |
xmllint --xpath '/download-area/files/file[2]/url/text()' -)
Para valores como os que não contêm caracteres de nova linha, você pode usar bash
' readarray
as:
readarray -t var < <(
xmlstarlet sel -t -v /download-area/files/file/url <<< "$XML")
Ou
readarray -t var < <(
xml2 <<< "$XML" | sed -n 's|^/download-area/files/file/url=||p')
Ou:
readarray -t var < <(
xml_grep --text_only /download-area/files/file/url <<< "$URL")
Considere usar sed
para analisar a saída de xmllint
. Observe a expressão XPath encurtada!
URL=$( echo $XML | xmllint --xpath "//url" - | sed -e 's/<url>//g' -e 's/<\/url>/\n/g' )
printf "%s\n" "$URL"
Isso produzirá os URLs um por linha