J'ai un fichier XML avec le contenu:
<?xml version="1.0" encoding="utf-8"?>
<job xmlns="http://www.sample.com/">programming</job>
J'ai besoin d'un moyen d'extraire ce qui est dans les balises <job..>
</job>
, programmin dans ce cas. Cela devrait être fait à l'invite de la commande linux, en utilisant grep/sed/awk.
Est-ce que vous devez vraiment utiliser uniquement ces outils? Ils ne sont pas conçus pour le traitement XML, et bien qu'il soit possible d'obtenir quelque chose qui fonctionne correctement la plupart du temps, cela échouera dans les cas Edge, comme l'encodage, les sauts de ligne, etc.
Je recommande xml_grep:
xml_grep 'job' jobs.xml --text_only
Ce qui donne la sortie:
programming
Sous Ubuntu/Debian, xml_grep est dans le paquetage xml-twig-tools.
grep '<job' file_name | cut -f2 -d">"|cut -f1 -d"<"
Utiliser xmlstarlet:
echo '<job xmlns="http://www.sample.com/">programming</job>' | \
xmlstarlet sel -N var="http://www.sample.com/" -t -m "//var:job" -v '.'
N'utilisez pas d'analyse XML basée sur les lignes et les expressions régulières. C'est une mauvaise idée. Vous pouvez avoir un code XML sémantiquement identique avec un formatage différent, et l'analyse syntaxique basée sur les expressions rationnelles et les lignes ne peut tout simplement pas y faire face.
Des choses comme les étiquettes unaires et le retour à la ligne variable - ces extraits «disent» la même chose:
<root>
<sometag val1="fish" val2="carrot" val3="narf"></sometag>
</root>
<root>
<sometag
val1="fish"
val2="carrot"
val3="narf"></sometag>
</root>
<root
><sometag
val1="fish"
val2="carrot"
val3="narf"
></sometag></root>
<root><sometag val1="fish" val2="carrot" val3="narf"/></root>
Espérons que cela montre clairement pourquoi il est difficile de créer un analyseur basé sur les expressions rationnelles/lignes. Heureusement, vous n'en avez pas besoin. De nombreux langages de script ont au moins une, parfois plus d'options d'analyse.
Comme l'a déjà mentionné une affiche, xml_grep
est disponible. C'est en fait un outil basé sur la bibliothèque XML::Twig
Perl. Cependant, il utilise des "expressions xpath" pour trouver quelque chose et différencie la structure du document, les attributs et le "contenu".
Par exemple.:
xml_grep 'job' jobs.xml --text_only
Cependant, dans l’intérêt de fournir de meilleures réponses, voici quelques exemples de "lancez votre propre" en fonction de vos données source:
Première manière:
Utilisez twig handlers
qui capture les éléments d’un type particulier et les applique. L'avantage de le faire de cette façon est qu'il analyse le XML "au fur et à mesure" et vous permet de le modifier en vol si vous en avez besoin. Ceci est particulièrement utile pour rejeter du XML "traité" lorsque vous travaillez avec des fichiers volumineux, en utilisant purge
ou flush
:
#!/usr/bin/Perl
use strict;
use warnings;
use XML::Twig;
XML::Twig->new(
twig_handlers => {
'job' => sub { print $_ ->text }
}
)->parse( <> );
Qui utilisera <>
pour prendre une entrée (intégrée ou spécifiée via la ligne de commande ./myscript somefile.xml
) et la traiter - chaque élément job
sera extrait et imprimera le texte associé. (Vous voudrez peut-être que print $_ -> text,"\n"
insère un saut de ligne).
Parce qu'il correspond aux éléments 'job', il va également correspondre aux éléments de travail imbriqués:
<job>programming
<job>anotherjob</job>
</job>
Correspondra deux fois, mais imprimera aussi une partie de la sortie deux fois. Vous pouvez toutefois faire correspondre le /job
à la place si vous préférez. Utilement - cela vous permet par exemple imprimez et supprimez un élément ou copiez-collez-en un en modifiant la structure XML.
Vous pouvez également analyser en premier et imprimer en fonction de la structure:
my $twig = XML::Twig->new( )->parse( <> );
print $twig -> root -> text;
Comme job
est votre élément racine, il suffit d’en imprimer le texte.
Mais nous pouvons être un peu plus perspicaces et rechercher job
ou /job
et l’imprimer spécifiquement à la place:
my $twig = XML::Twig->new( )->parse( <> );
print $twig -> findnodes('/job',0)->text;
Vous pouvez également utiliser l'option XML::Twig
s pretty_print
pour reformater votre XML:
XML::Twig->new( 'pretty_print' => 'indented_a' )->parse( <> ) -> print;
Il existe une variété d'options de format de sortie, mais pour un XML plus simple (comme le vôtre), la plupart auront un aspect similaire.
il suffit d'utiliser awk, pas besoin d'autres outils externes. Ci-dessous fonctionne si vos balises désirées apparaissent dans multitine.
$ cat file
test
<job xmlns="http://www.sample.com/">programming</job>
<job xmlns="http://www.sample.com/">
programming</job>
$ awk -vRS="</job>" '{gsub(/.*<job.*>/,"");print}' file
programming
programming
En supposant la même ligne, entrée de stdin:
sed -ne '/<\/job>/ { s/<[^>]*>\(.*\)<\/job>/\1/; p }'
notes: -n
cesse de tout afficher automatiquement; -e
signifie que c'est un one-liner (avec un script) /<\/job>
se comporte comme un grep; s
supprime les attributs opentag + et l'étiquette finale; ;
est une nouvelle déclaration; p
impressions; {}
permet au grep de s’appliquer aux deux instructions.
Utilisation de sed command:
Exemple:
$ cat file.xml
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
$ cat file.xml | sed -ne '/<heading>/s#\s*<[^>]*>\s*##gp'
Reminder
Explication:
cat file.xml | sed -ne '/<pattern_to_find>/s#\s*<[^>]*>\s*##gp'
n
- supprime l'impression de toutes les lignese
- script
/<pattern_to_find>/
- recherche les lignes contenant le motif spécifié, ce qui pourrait être par exemple .<heading>
next est la partie de substitution s///p
qui supprime tout sauf la valeur souhaitée, où /
est remplacé par #
pour une meilleure lisibilité:
s#\s*<[^>]*>\s*##gp
\s*
- inclut des espaces si existants (idem à la fin)<[^>]*>
représente <xml_tag>
en tant que cause alternative regex non gloutonne <.*?>
ne fonctionne pas pour sed
g - remplace tout, par ex. fermeture de la balise xml </xml_tag>
Un peu tard pour le spectacle.
xmlcutty découpe les nœuds à partir de XML:
$ cat file.xml
<?xml version="1.0" encoding="utf-8"?>
<job xmlns="http://www.sample.com/">programming</job>
<job xmlns="http://www.sample.com/">designing</job>
<job xmlns="http://www.sample.com/">managing</job>
<job xmlns="http://www.sample.com/">teaching</job>
L'argument path
nomme le chemin d'accès à l'élément que vous voulez couper. Dans ce cas, comme les tags ne nous intéressent pas du tout, nous renommons le tag en \n
, nous obtenons donc une liste de Nice:
$ xmlcutty -path /job -rename '\n' file.xml
programming
designing
managing
teaching
Notez que le XML n'était pas valide pour commencer (pas d'élément racine). xmlcutty peut aussi fonctionner avec du XML légèrement cassé.
Que diriez-vous:
cat a.xml | grep '<job' | cut -d '>' -f 2 | cut -d '<' -f 1