Je travaille sur un script shell Linux pour trouver des informations dans un fichier XML à l'aide de grep
. Je suis sur un mac qui, je l’espère, n’a pas trop d’importance.
Pour trouver les informations dont j'ai besoin, je lance:
grep -oP "<title>(.*)</title>" temp.xml
Je reçois en retour une liste de correspondances et cela inclut la balise <title>
.
Comment obtenir une liste contenant uniquement les informations contenues dans la balise title
mais sans la balise title
à l'aide de grep?
Je ne vois pas pourquoi vous voudriez utiliser grep pour cela, alors que cela peut être résolu avec une expression XPath triviale:
//title/text()
Il existe de nombreux outils de ligne de commande pour XPath et ils sont généralement fournis avec le système d’exploitation.
Les réponses à cette question sur Stack Overflow listent un certain nombre de ces outils.
Le problème avec grep
est qu’il s’agit d’un outil générique pour le traitement de texte et qu’il ne connaît aucune structure XML. Pour un scénario très simple, vous pouvez le faire fonctionner . Si le document est complexe ou si vous l'utilisez dans un script qui survivra des mois ou des années et non pas à un travail ponctuel, vous risquez de vous sentir désolé des résultats.
XPath facilite la distinction entre les balises de même nom apparaissant dans différents contextes d'un document.
<article>
<author>
<name>Jon Doe</name>
<title>Chief Editor</title>
</author>
<title>On the Benefits of grep</title>
<publicationDate>2018-02-12</publicationDate>
<text>blah blah blah</text>
</article>
Extraire le titre de l'article représenté par ce document avec grep
échouerait si vous utilisiez l'une des autres réponses postées ici. Vous pouvez techniquement écrire l'expression régulière pour obtenir ce dont vous avez besoin, mais c'est beaucoup plus facile avec XPath.
/article/title/text()
Si vous savez que vous traitez avec un document trivial et que le format ne change pas ou s'il s'agit d'un travail ponctuel où vous pouvez rapidement valider les résultats, vous pouvez choisir grep
comme expliqué par d'autres.
Puisque vous utilisez déjà grep -P
, pourquoi n'utilisez-vous pas ses fonctionnalités?
grep -oP '(?<=<title>).*?(?=</title>)'
Dans le cas général, XPath est la solution correcte, mais pour les scénarios de jouets, oui, Virginia, cela peut être fait.
Ce n'est pas la meilleure solution, je chercherais XML lib dans bash mais vous pouvez le faire:
grep -oP "<title>(.*)</title>" temp.xml | cut -d ">" -f 2 | cut -d "<" -f 1
Vous pouvez installer xgrep en utilisant xpath comme suggéré dans La réponse de Tom
grep -oP "<foo>(.*)</foo>" "XML.xml" | sed -n 's/.*<foo>\([^<]*\)<\/foo>.*/\1/p' >> "foo.txt"