J'ai l'URL (voir ci-dessous) d'une certaine page Web qui énumère de nombreuses versions différentes d'un logiciel.
URL=http://ftp.gnu.org/gnu/wget/
Le one-liner suivant m'obtient la dernière version de la balle de tar et son file de signature hors du code HTML.
wget -qO- http://ftp.gnu.org/gnu/wget/ | grep tar | cut -d\" -f6 | tail -n4 | grep gz
Probablement pas le plus court un liner efficace, mais bon, j'apprends et je suis ouvert pour les commentaires. Le résultat de ce qui précède est le suivant:
wget-1.15.tar.gz wget-1.15.tar.gz.sig
Maintenant, la prochaine étape logique (pour moi au less), est de diriger la sortie ci-dessus dans sed
et append l' $URL
à l'avant de chaque ligne afin que la sortie ressemble à:
http://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz http://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz.sig
Et puis je veux redirect ça dans wget
pour download les files.
La question est la suivante: Comment puis-je append la valeur de la variable bash $URL
à l'avant de chaque ligne de sortie en utilisant sed
? J'ai essayé ce qui suit:
sed "s/^/$URL/"
Mais cela ne fait que me donner l'erreur:
sed: -e expression #1, char 11: unknown option to `s'
Je sais aussi que le concept de base est bon, parce que quand j'utilise ce qui suit, j'obtiens de bons résultats …
VAR="Gorauskas, " echo "Jonas" | sed "s/^/$VAR/"
Donc, je suppose que j'ai besoin d'échapper à tout le caractère /
dans la variable $URL
… Suis-je sur la bonne voie?
Utilisez un séparateur différent qui ne contient aucun des caractères de la variable.
Par exemple,
sed "s|^|$URL|"
(Si vous utilisez /
comme séparateur et que le motif ou le rlocation contient aussi /
, alors vous devriez les échapper.)
Ce que vous faites jusqu'à présent peut être remplacé par un appel d' awk
:
wget ... | awk -F\" '$6 ~ "gz$" { lastline=thisline; thisline=$6;}; '\ 'END {print lastline; print thisline;}'
Et, bien sûr, awk peut aussi append l'URL:
awk -F\" -v baseurl="http://ftp.gnu.org/gnu/wget/" \ '$6 ~ "gz" { lastline=thisline; thisline=$6;}; '\ 'END {print baseurl lastline; print baseurl thisline;}'
Vous pouvez utiliser l'option --base
wget
ici:
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/
Vous pouvez également faire tout cela directement comme ceci:
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/{}
Cela transmet la sortie du 1er wget
à xargs
qui remplace la string {}
par chacun des résultats de la command piped.
Et vous pouvez sauter certaines étapes d'parsing avec une certaine supercherie:
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/{}
Ici, nous utilisons des PCRE ( -P
) avec grep
et -o
afin d'imprimer seulement la partie appariée de la ligne et -m 2
pour imprimer seulement les 2 premières correspondances. L'appel tac
inverse l'input de sorte que les 2 premières correspondances sont en fait les dernières ( tac
inverse son input, imprime la dernière ligne comme première, avant-dernière comme seconde etc.).
Le \K
dans l'expression régulière indique à grep
d'ignorer ce qui a précédé le \K
pour qu'il ne soit pas imprimé en utilisant -o
.
Une autre approche, plus proche de ce que vous aviez en tête, serait de lire les files cibles dans une boucle:
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