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]>
Nous pouvons atteindre cet objectif grâce à l'outil sed
NAME _ - é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 à sed
quoi imprimer.
Cette commande supplémentaire est la commande d'impression p
name__, ajoutée à la fin du script. Si sed
n'a pas été démarré avec une option -n
, la commande p
dupliquera 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 d
va 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
I
et 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 s
substituera les chaînes qui mach à l'expression /<[^>]*>/
par une chaîne vide //
- s/<old>/<new>/
.
L'indicateur de modèle g
appliquera 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 sed
name __ 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: