Usando sed para adicionar um URL ao início de cada linha

6

Eu tenho o URL (veja abaixo) de uma determinada página da web que lista muitos diferentes versões de um pacote de software.

URL=http://ftp.gnu.org/gnu/wget/

O seguinte one-liner me traz a última versão do tar ball e sua assinatura arquivo fora do HTML.

wget -qO- http://ftp.gnu.org/gnu/wget/ | grep tar | cut -d\" -f6 | tail -n4 | grep gz

Provavelmente não o forro mais curto e eficiente, mas ei, estou aprendendo e Estou aberto para feedback. O resultado do acima é isto:

wget-1.15.tar.gz
wget-1.15.tar.gz.sig

Agora, o próximo passo lógico (pelo menos para mim) é canalizar a saída acima para sed e acrescente o $URL à frente de cada linha para que a saída pareça como:

http://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz
http://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz.sig

E então eu quero redirecionar isso de volta para wget para baixar os arquivos.

A pergunta é a seguinte: Como eu adiciono o valor da variável bash $URL ao a frente de cada linha de saída usando sed ? Eu tentei o seguinte:

sed "s/^/$URL/"

Mas isso só me dá o erro:

sed: -e expression #1, char 11: unknown option to 's'

Eu também sei que o conceito básico é bom, porque quando eu uso o seguinte, eu obter bons resultados ...

VAR="Gorauskas, "
echo "Jonas" | sed "s/^/$VAR/"

Então, meu palpite é que eu preciso de alguma forma escapar todo o caractere / no $URL variable ... Estou no caminho certo?

    
por λ Jonas Gorauskas 24.02.2014 / 08:27

4 respostas

11

Use um separador diferente que não contenha nenhum dos caracteres da variável.

Por exemplo,

sed "s|^|$URL|"

(Se você usa / como o separador e o padrão ou a substituição também contém / , então você precisa escapar deles.)

    
por 24.02.2014 / 08:31
8

O que você faz até agora pode ser substituído por uma chamada awk :

wget ... | awk -F\" '$6 ~ "gz$" { lastline=thisline; thisline=$6;}; '\
  'END {print lastline; print thisline;}'

E, claro, o awk também pode adicionar o URL:

awk -F\" -v baseurl="http://ftp.gnu.org/gnu/wget/" \
  '$6 ~ "gz" { lastline=thisline; thisline=$6;}; '\
  'END {print baseurl lastline; print baseurl thisline;}'
    
por 24.02.2014 / 08:43
8

Você pode usar a opção wget de --base aqui:

wget -qO- http://ftp.gnu.org/gnu/wget/ |
  cut -d\" -sf6 |
  grep '\.tar\.gz' |
  tail -n2 |
  wget -i - --base=http://ftp.gnu.org/gnu/wget/
    
por 24.02.2014 / 09:50
5

Você também pode fazer tudo diretamente assim:

wget -qO- http://ftp.gnu.org/gnu/wget/ | grep tar.gz | cut -d\" -f6 | 
 tail -n2 | xargs -I{} wget http://ftp.gnu.org/gnu/wget/{}

Isso passa a saída do primeiro wget para xargs que substitui a string {} com cada um dos resultados do comando canalizado.

E você pode pular algumas etapas de análise com alguns truques:

wget -qO- http://ftp.gnu.org/gnu/wget/ | tac | grep -Pom 2 'href="\K(.+?.tar.gz)' | 
xargs -I{} wget http://ftp.gnu.org/gnu/wget/{}

Aqui, estamos usando PCREs ( -P ) com grep e -o para que apenas imprima a parte correspondente da linha e -m 2 para imprimir apenas as duas primeiras correspondências. A chamada tac inverte a entrada para que as primeiras 2 correspondências sejam realmente as últimas ( tac inverte sua entrada, imprime a última linha como primeiro, penúltimo como segunda etc.).

O \K na expressão regular informa grep para ignorar o que veio antes do \K , para que não seja impresso ao usar -o .

Outra abordagem, mais próxima do que você tinha em mente, seria ler os arquivos de destino em um loop:

wget -qO- http://ftp.gnu.org/gnu/wget/ |tac | 
 grep -Pom 2 'href="\K(.+?.tar.gz)' | 
    while read target; do 
        wget http://ftp.gnu.org/gnu/wget/"$target"; 
    done 
    
por 24.02.2014 / 13:36

Tags