J’ai un processus dans lequel je dois copier toutes les images d’une page Web. J’avais l’habitude d’exécuter ce processus avec xmllint
, qui traitera un fichier XML ou HTML et imprimera les entrées que vous spécifiez. Mais lorsque mon fournisseur d’hôte de serveur a mis à niveau ses systèmes, il n’a pas inclus xmllint
. J’ai donc dû trouver un autre moyen d’extraire une liste d’images d’une page HTML. Il s’avère que vous pouvez le faire dans Bash.
Vous ne pensez peut-être pas que Bash peut analyser les fichiers de données, mais il le peut avec une réflexion intelligente. Bash, comme les autres shells UNIX avant lui, peut analyser les lignes une par une à partir d’un fichier via le read
déclaration.
Par défaut, le read
L’instruction scanne une ligne de données et la divise en champs. D’habitude, read
divise les champs à l’aide d’espaces et de tabulations, avec des retours à la ligne terminant chaque ligne, mais vous pouvez modifier ce comportement en définissant le séparateur de champ interne (IFS
) et le délimiteur de fin de ligne (-d
).
Pour analyser un fichier HTML à l’aide de read
, met le IFS
à un symbole supérieur à (>
) et le délimiteur d’un symbole inférieur à (<
). Chaque fois que Bash scanne une ligne, il analyse jusqu’à la suivante <
(le début d’une balise HTML) divise ensuite ces données à chaque >
(la fin d’une balise HTML). Cet exemple de code prend une ligne d’entrée et divise les données en TAG
et VALUE
variables:
local IFS='>' read -d '<' TAG VALUE
Explorons comment cela fonctionne. Considérez ce simple fichier HTML:
<img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png" alt="My logo" /> <p>some text</p>
La première fois read
analyse ce fichier, il s’arrête au premier <
symbole. Puisque <
est le premier caractère de cet exemple d’entrée, ce qui signifie que Bash trouve une chaîne vide. La résultante TAG
et VALUE
les chaînes sont également vides. Mais c’est bien pour mon cas d’utilisation.
La prochaine fois que Bash lit l’entrée, il obtient img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png"↲alt="My logo" />↲
avec une nouvelle ligne juste avant l’alt, et s’arrête avant le <
symbole sur la ligne suivante. Puis read
divise la ligne au >
symbole, qui laisse TAG
avec img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png"↲alt="My logo" /
et VALUE
avec une nouvelle ligne vide.
La troisième fois read
analyse le fichier HTML, il obtient p>some text
. Bash divise la chaîne au >
résultant en TAG
contenant p
et VALUE
avec some text
.
Maintenant que vous comprenez comment utiliser read
, il est facile d’analyser un fichier HTML plus long avec Bash. Commencez avec une fonction Bash appelée xmlgetnext
pour analyser les données en utilisant read
, puisque vous le ferez encore et encore dans le script. J’ai nommé ma fonction xmlgetnext
pour me rappeler que c’est un remplacement pour le Linux xmllint
programme, mais j’aurais pu le nommer aussi facilement htmlgetnext
.
xmlgetnext () { local IFS='>' read -d '<' TAG VALUE }
Maintenant appelle ça xmlgetnext
fonction pour analyser le fichier HTML. C’est mon complet htmltags
scénario:
#!/bin/sh # print a list of all html tags xmlgetnext () { local IFS='>' read -d '<' TAG VALUE } cat $1 | while xmlgetnext ; do echo $TAG ; done
La dernière ligne est la clé. Il parcourt le fichier en utilisant xmlgetnext
pour analyser le HTML et n’imprime que le TAG
entrées. Et à cause de comment echo
fonctionne avec les séparateurs de champ standard, toutes les lignes comme img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png"↲alt="My logo" /
qui contiennent une nouvelle ligne sont imprimés sur une seule ligne, comme img src="https://www.cloudsavvyit.com/8315/parsing-html-in-bash/logo.png" alt="My logo" /
.
Pour récupérer uniquement la liste des images, j’exécute la sortie de ce script via grep
pour n’imprimer que les lignes qui ont un img
balise au début de la ligne.