Récupérer variables entre plusieurs balises sur même ligne

Fermé
spctoma - Modifié par spctoma le 18/01/2013 à 00:57
 spctoma - 18 janv. 2013 à 12:47
Bonjour,

Je dispose dans mon script d'une variable "fichedesc" qui contient la chaine de caractère suivante :

fichedesc="<mId>AHBU30008X</mId> <mDesc>Descr. de la fiche</mDesc> <mPages>3</mPages>"

Pour récupérer le contenu des balises mDesc et mPages, je fais :
mDesc='echo $fichedesc | sed -n '/<mDesc>.*<\/mDesc>/s/[^>]*>\([^<]*\)<.*/\1/p''
mPages='echo $fichedesc | sed -n '/<mPages>.*<\/mPages>/s/[^>]*>\([^<]*\)<.*/\1/p''


Mais j'obtiens : AHBU30008X dans mDesc et mPages ...
Je ne comprends pas pourquoi mon sed ne récupère que le contenu des premières balises.

Pourriez vous m'aider s'il vous plaît ?

Merci d'avance

4 réponses

Utilisateur anonyme
18 janv. 2013 à 12:08
while read -r line
do
   case "$line" in
      \<Fiche\>) fic=1; toBsent="";;
      \</Fiche\>) echo "envoi \"$toBsent\" >> fichier.js"; fic=0;;
   esac
   test $fic -eq 1 && case $line in
         *mEcsIdCode*|*mType*|*mNbPages*|*mDescription*) line="${line#*>}"
            toBsent="$toBsent
${line%%<*}";;
      esac
done < $tonFichier

par contre, il n'y a pas de d'indicateur de progression.
c'est probablement perfectible (je ne comprend pas tout ton code, il me pique un peu les yeux)

si le fichier est vraiment gros, ça s'adaptera facilement en awk.
1
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 407
18 janv. 2013 à 06:31
Salut,

Parce que le "/<mDesc>.*<\/mDesc>/" ne sert à rien dans ta syntaxe. On utilise un motif que pour cibler une ligne particulière dans un fichier, mais toi tu n'as qu'une ligne à traiter, donc que tu mettes "/<mPages>.*<\/mPages>/" ou "/<mDesc>.*<\/mDesc>/", c'est toujours la même ligne qui est traitée dans sa totalité et non à partir du motif comme tu l'espérais ;-\

$ sed -n 's/[^>]*>\([^<]*\)<.*/\1/p' <<<${fichedesc}
AHBU30008X

$ sed -n 's/.*<mPages>\([^<]*\)<.*/\1/p' <<<${fichedesc}
3

0
zipe31 Messages postés 36402 Date d'inscription dimanche 7 novembre 2010 Statut Contributeur Dernière intervention 27 janvier 2021 6 407
18 janv. 2013 à 07:34
On va même simplifié, enfin raccourcir la syntaxe, mais il faut impérativement que le motif cible soit le dernier sur la ligne :

$ sed -n 's/.*>\b\([^<]*\)<.*/\1/p' <<<${fichedesc}
3
0
J'avais fini par utliser la méthode suivante :
mDescriptionTemp=${fichedesc%%<mDescription*}
mDescription=${mDescriptionTemp##*mDescription>}
qui faisait l'affaire, mais ta solution étant plus propre, je vais l'utiliser ! Merci beaucoup en tout cas
0
Si tu peux éviter d'appeler une commande externe, c'est quand même mieux.
Tu devrais gagner en performance en n'utilisant que les substitutions de paramètres.

L'usage d'une variable temporaire n'est pas indispensable.
0
J'utilise la méthode de zipe31 (merci à lui) :
mDescription='echo $fichedesc | sed -n 's/.*mDescription>\b\([^<]*\)<.*/\1/p''
mNbPages='echo $fichedesc | sed -n 's/.*mNbPages>\b\([^<]*\)<.*/\1/p''


Qui marche bien. qqchosequicommenceparQ tu penses qu'en terme de performance il vaut mieux utiliser quoi ? Etant donné que j'ai 10 000 variables $fichedesc à traiter, je suis soucieux de la perf :)

Dans une boucle je fais à chaque fois :
fichedesc='sed -n "/<mEcsIdCode>"$fiche"<\/mEcsIdCode>/,/Fiche>/p" $lienFicDescFicheLight'

puis je récupère le contenu des balises <mNbPage> et <mDescription>

J'ai un fichier xml $lienFicDescFiches de la forme suivante, avec 10 000 <Fiche> soit au total plus de 130 000 lignes :
<Fiche>
<mEcsIdCode>id de la fiche</mEcsIdCode>
     <balise1> </balise1>
    <balise 2> </balise 2>
    <mType> </mType>
    <mNbPages> </mNbPages>
    <mDescription> </mDescription>
</Fiche>


Pensez vous que je puisse optimiser mieux les performences ? (c'est assez long à tourner) :

lienFicDescFicheLight=./temp_FicDescFichesLight.xml
        #Je créée un fichier xml temporaire ne contenant que les balises que je veux récupèrer
	egrep -i '(mEcsIdCode|mType|mNbPages|mDescription|</Fiche>)' $lienFicDescFiches > $lienFicDescFicheLight
	
       #J'ai la liste des fiches qui m'intéressent dans le fichier "temp_liste_xml_fiches"
	for fiche in 'cat ./temp_liste_xml_fiches | sort | uniq | tr -d ' ''
	do
		fichedesc='sed -n "/<mEcsIdCode>"$fiche"<\/mEcsIdCode>/,/Fiche>/p" $lienFicDescFicheLight'
                #Traitement de la DESCRIPTION :
		#mDescriptionTemp=${fichedesc%%</mDescription*}
		#mDescription=${mDescriptionTemp##*mDescription>}
		mDescription='echo $fichedesc | sed -n 's/.*mDescription>\b\([^<]*\)<.*/\1/p''
		echo 'mDescription["'$fiche'"]="'$mDescription'";' >> ./images/function.js
		#Traitement du NB DE PAGES :
                #mNbPagesTemp=${fichedesc%%</mNbPages*}
		#mNbPages=${mNbPagesTemp##*mNbPages>}
		mNbPages='echo $fichedesc | sed -n 's/.*mNbPages>\b\([^<]*\)<.*/\1/p''
		echo 'mNbPages["'$fiche'"]='$mNbPages';' >> ./images/function.js
		#Traitement du TYPE :
		#mTypeTemp=${fichedesc%%</mType*}
		#mType=${mTypeTemp##*mType>}
		mType='echo $fichedesc | sed -n 's/.*mType>\b\([^<]*\)<.*/\1/p''
		echo 'mType["'$fiche'"]="'$mType'";' >> ./images/function.js
		
		echo -ne "\rIndexage des fiches pour la fonction recherche: ${currentFiche}/${nombreFiches} (${progression}%)\r" | awk '{printf("%s", $0)}'
	done
0
Désolé si ça pique les yeux, je ne suis pas un expert en shell, j'arrive juste à faire marcher quelques trucs :)

Ce sont des déclarations de tableaux en javascript que je veux exporter pour chaque balises

J'ai adapté ce que tu m'as donné et ... ça marche nickel ! Et c'est bien plus rapide qu'avant.
Merci beaucoup :)

while read -r line
		do
		  case "$line" in
		      \<Fiche\>)
				fic=1; toBsent="";;
		      \</Fiche\>)
				echo $toBsent >> ./images/liste_mop.js
				fic=0;;				
		  esac

		  test $fic -eq 1 && case $line in
			*mEcsIdCode*)
			line="${line#*>}"
			fiche=${line%%<*};;
			
			  *mType*)
			  line="${line#*>}"
			  toBsent="$toBsent
		mType['$fiche']='${line%%<*}'; ";;

			  *mNbPages*)
			  line="${line#*>}"
			  toBsent="$toBsent
		mNbPages['$fiche']='${line%%<*}'; ";;

			  *mDescription*)
			  line="${line#*>}'"
			  toBsent="$toBsent
		mDescription['$fiche']='${line%%<*}'; ";;
		      esac
		done < $lienFicDescFiches	


ça me donne le fichier javascript sous la forme :

mDescription['878AKJ9918']='bla bla '; mType['878AKJ9918']='truc'; mNbPages['878AKJ9918']='3';
mDescription['4516HJ4952']='bla bla '; mType['4516HJ4952']='truc'; mNbPages['4516HJ4952']='3';
0