Utilisation de sed pour extraire du texte entre 2 balises

16

J'ai un fichier .xml et j'essaie de faire une "installation de groupe" sur une machine RHEL6 car il y a plusieurs centaines de bibliothèques dans ce fichier .xml ... (près de 16 000 lignes).

J'essaie donc d'extraire les noms de groupe contenus dans le fichier .xml qui a cette structure:

<b>
<group>
<id> group name </id>
   <packages>
   ...
   </packages>
<id> group name 2 </id>
   <packages>
   ...
   </packages>
<id> etc... </id>
</group>
</b>

En gros, c'est ce que j'ai essayé:

sed -n '/<id>/,/<\/id>/p' test1.txt > test2.txt

J'ai copié le fichier .xml dans test1.txt. J'essaye d'extraire les noms de groupe du test1.txt dans un deuxième fichier appelé test2.txt. Cependant, avec la ligne ci-dessus, il extrait tout de la première <id>balise à la dernière </id>balise de mon fichier. Comment puis-je changer mon code pour l'extraire plusieurs fois?

Ma deuxième question serait: le plugin -downloadonly fonctionne-t-il aussi avec les groupes pour yum?

Guillaume F.
la source
3
Oh mon cher, en analysant à nouveau XML avec des expressions rationnelles. C'est demander des ennuis ...
gniourf_gniourf
1
Jetez un oeil à cela
alecail
8
Il ne demande pas d' analyser XML, mais d'extraire une correspondance spécifique d'octets. Il y a une différence fondamentale.
Runium

Réponses:

31

On dirait que ce dont vous avez besoin est plus quelque chose comme

sed -n 's:.*<id>\(.*\)</id>.*:\1:p'

(en supposant comme dans votre échantillon que le <id>et </id>sont sur la même ligne et qu'il n'y en a qu'un <id>...</id>par ligne).

Ou utilisez un outil compatible XML:

xmlstarlet sel -t -v '//id' -n
Stéphane Chazelas
la source
C'est très bien, bravo!
fduff
2

Veuillez essayer avec

xml_grep 'id' file.xml --text_only
Kiran Kumar Reddy M
la source
1
$ echo '<id>I am a sample group</id>' | sed 's/<\/\?[^>]\+>//g'
I am a sample group
$

Cela fonctionnera avec n'importe quelle balise, bien sûr aussi avec des <a href="...">...</a>ancres. Aucun GNUismes utilisé - le support de base des regex sedsuffira.
Cependant : veuillez noter que les balises d'ouverture et de fermeture doivent être sur la même ligne, sinon l'instruction devrait être réécrite à nouveau.

erreur de syntaxe
la source
1

Il s'agit de XML, vous devez utiliser un analyseur XML. Voici une solution utilisant XMLStarlet :

$ xml sel -t -v '//group/id' -nl data.xml
 group name
 group name 2

L'expression XPath //group/idsélectionnera n'importe quel idnœud sous un groupnœud. Le -t -vmoyen "utilise le modèle suivant pour extraire les valeurs". Le -nlà la fin s'assurera que la sortie se termine par une nouvelle ligne.

L'exemple ci-dessus utilise un fichier XML identique au vôtre, mais avec toute ligne contenant ...supprimé.

Kusalananda
la source
0

J'ai lu cet article dans le but de résoudre le problème d'extraction de Reqd. Paquets du DVD RHEL 7.3 repos.xml, ce que je pense est exactement ce que l'auteur ci-dessus essayait de faire. J'espère donc que ce script pourra aider quelqu'un d'autre… Je l'ai utilisé plusieurs fois maintenant.

J'ai donc dû installer le groupe "GNOME DESKTOP" sur mon serveur RHEL7 "Installation minimale" qui n'avait pas de X / GUI configuré.

[root@rac01]# yum group list
Loaded plugins: ulninfo
There is no installed groups file.

Hmmmmm… pas de liste de groupe sur le DVD pour yum (yep, j'ai essayé tous les correctifs habituels de "google" et je n'ai jamais travaillé) alors j'ai eu recours à une source matérielle de la liste à partir de xml.

  1. Montez le DVD.
  2. Trouvez le fichier XML avec ma liste de packages requise.
  3. Extrayez la liste des groupes de packages.
  4. Parcourez la liste des packages et installez-la (y compris les dépendances).
  5. En supposant que vous ayez couru createrepo /your/local_rpms/dir.

    sudo su -
    mkdir /mnt/sr0
    mount /dev/sr0 /mnt/sr0
    cd /mnt/sr0
    
    FILE=$(find . -name "*.xml" | xargs grep '<id>gnome-desktop<\/id>'| cut -d: -f1)
    PKGLIST=$(sed -n '/<id>gnome-desktop<\/id>/,/<\/packagelist>/p' $FILE \
    | sed  -n  '/^ *<packagelist> *$/,/^ *<\/packagelist> *$/{/<packagereq type>/{d};p}' \
    | cut -d'>' -f2 \
    | cut -d'<' -f1)
    
    for p in ${PKGLIST}
       do
        yum deplist ${p}* | awk '/provider:/ {print $2}' | sort -u | xargs yum -y install
    done
    
capitainek
la source