web-dev-qa-db-fra.com

Extraire le contenu d'un fichier entre deux modèles de correspondance (extraire uniquement le HTML d'un fichier)

J'ai un fichier qui contient différents types de formats de texte, mon objectif est d'extraire uniquement une partie HTML et de créer un fichier avec ce code HTML. Je pense que c'est possible avec grep ou awk. Mon fichier contient aussi des lignes comme ceci:

Sender name `<[email protected]>`

J'ai écrit ce script cat file1.html | grep -E "<[^>]*>". Mais le problème est qu’il affiche également les lignes sous la forme Sender name, etc. Je souhaite extraire le contenu uniquement après la balise <html>. Donc ce n'est pas utile pour moi:

Return-Path: <[email protected]>
    for <test@localhost> (single-drop); Thu, 21 Sep 2017 18:34:07 +0400 (+04)
Return-path: <[email protected]>
    (envelope-from <[email protected]>)
References: <[email protected]>
From: test user <[email protected]>
X-Forwarded-Message-Id: <[email protected]>
Message-ID: <[email protected]>
In-Reply-To: <[email protected]>
2
DaviD

Nous pouvons atteindre cet objectif grâce à l'outil sedNAME _ - éditeur de flux pour le filtrage et la transformation de texte . La réponse courte est donnée sous au point 5 ci-dessous. Mais j'ai décidé d'écrire une explication détaillée.

0. Commençons par créer un fichier simple pour tester nos commandes:

$ printf '\nTop text\nSender <[email protected]>\n\n<html>\n\tThe inner text 1\n</html>\n\nMiddle text\n\n<HTML>\n\tThe inner text 2\n</HTML>\n\nBottom text\n' | tee example.file

Top text
Sender <[email protected]>

<html>
        The inner text 1
</html>

Middle text

<HTML>
        The inner text 2
</HTML>

Bottom text

1. Nous pouvons rogner tout ce qui se trouve entre les balises <html> et </html>, y compris leurs noms, de la manière suivante:

$ sed -n -e '/<html>/,/<\/html>/p' example.file

<html>
        The inner text 1
</html>
  • L'option -e script (--expression=script) ajoute un script aux commandes à exécuter. Dans ce cas, le script ajouté est '/<html>/,/<\/html>/p'. Bien que nous n’ayons qu’un seul script, nous pouvons omettre cette option.

  • L'option -n (--quiet, --silent) supprime l'impression automatique de l'espace modèle, et avec cette option, nous devrions utiliser des commandes supplémentaires pour indiquer à sedquoi imprimer.

  • Cette commande supplémentaire est la commande d'impression pname__, ajoutée à la fin du script. Si sedn'a pas été démarré avec une option -n, la commande pdupliquera l'entrée.

  • Enfin, par les deux modèles séparés par des virgules - /<html>/,/<\/html>/ - nous pouvons spécifier une plage. Veuillez noter que nous utilisons \ pour échapper au caractère spécial / qui joue le rôle de délimiteur ici.

2. Si nous voulons tout rogner entre les balises <html> et </html>, sans les imprimer, nous devrions ajouter quelques commandes supplémentaires:

$ sed -n '/<html>/,/<\/html>/{ /html>/d; p }' example.file

        The inner text 1
  • Les accolades, { et }, permettent de regrouper les commandes.

  • La commande dva supprimer chaque ligne qui correspond à l'expression html>.

3. Mais notre example.file a aussi des balises majuscules <HTML>. Nous devrions donc rendre la correspondance de modèle insensible à la casse. Nous pourrions y parvenir en ajoutant l'indicateur /I aux expressions régulières:

$ sed -n '/<html>/I,/<\/html>/I{ /html>/Id; p }' example.file

        The inner text 1
        The inner text 2
  • La correspondance entre le modificateur Iet l'expression régulière est une extension GNU qui fait correspondre le REGEXP sans tenir compte de la casse.

4. Si nous souhaitons supprimer toutes les balises HTML entre les balises <html>, nous pourrions ajouter une commande supplémentaire, qui analysera et "supprimera" les chaînes, qui commencez par < et finissez par >:

sed -n '/<html>/I,/<\/html>/I{ /html>/Id; s/<[^>]*>//g; p }' example.file
  • La commande ssubstituera les chaînes qui mach à l'expression /<[^>]*>/ par une chaîne vide // - s/<old>/<new>/.

  • L'indicateur de modèle gappliquera le remplacement à toutes les correspondances de l'expression rationnelle, pas seulement à la première.

Nous voudrions probablement omettre la commande delete dans ce cas:

sed -n '/<html>/I,/<\/html>/I{ s/<[^>]*>//g; p }' example.file

5. Pour apporter les modifications à la place du fichier et créer une copie de sauvegarde, nous pouvons utiliser l'option -i ou créer un nouveau fichier sur la sortie de sedname __ en redirigeant > vers le nouveau fichier:

sed -n '/<html>/I,/<\/html>/I p' example.file -i.bak
sed -n '/<html>/I,/<\/html>/I p' example.file > new.file

Références:

4
pa4080