Contenu | Rechercher | Menus

Annonce

Ubuntu 16.04 LTS
Commandez vos DVD et clés USB Ubuntu-fr !

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

#1 Le 15/05/2017, à 22:34

Arbiel

[Résolu] sed : substitution d'une chaîne de caractères par un fichier

Bonsoir

[N.B]
Sans rentrer dans la lecture détaillée de ce fil, sachez que la commande de substitution avec l'option e, telle que

sed -r "s/qqch/cat fichier/e" fichier_à_traiter

effectue d'abord la substitution de qqch par "cat fichier", puis exécute le commande qui en résulte. Elle n'est donc vraiment exploitable que si qqch est une ligne complète.
Il faut donc décomposer la ligne qui contient qqch en 3, puis exécuter la commande de substitution

sed -r "s/^(.*)(qqch)(.*)$/\1\n\2\n\3" fichier_à_traiter | sed -r "s/qqch/cat fichier/e"

[/N.B]


Pour substituer une chaîne de caractères par un fichier, j'ai écrit la commande

es "${gbl_xml}" | sed -r "s|<n-skl/>|cat /tmp/skolios.n-skl.xml|e" 1>/tmp/skolios.xml

"es" est une fonction qui envoie sur la sortie standard le contenu de la variable (echo) ou du fichier (cat) passé en paramètre.
La commande sed me retourne l'erreur

sh: 1: Syntax error: end of file unexpected

Par contre la commande

es "${gbl_xml}" | sed -r "s|<n-skl/>|cat /tmp/skolios.n-skl.xml|" 1>/tmp/skolios.xml

fonctionne comme prévu (elle remplace "<n-skl/>" par "cat /tmp/skolios.n-skl.xml").
Le fichier /tmp/skolios.n-skl-xml contient une succession de 113 éléments xml, 1 par ligne, tels que

<fichier idu="17501ad9-65f0-c0df-59f2-d8c9afae958e" date="2017-05-15 22:10:33+02:00">/home/remi/Documents/Programmation/scripts bash/wifi.sh<relatif>wifi.sh</relatif><droits>775 # -rwxrwxr-x</droits><proprio>1000 # remi</proprio><groupe>0 # root</groupe><taille>866</taille><sig type="md5" source="fichier">a6b179c3-8f32-f8f7-1353-354d3fea30d2</sig></fichier>

suivis par un retour à la ligne.

Je ne vois pas pourquoi la commande ne fonctionne pas.

À vrai dire, elle ne fonctionne pas non plus lorsque je remplace la lecture du fichier /tmp/skolios.n-skl-xml par l'appel de la procédure qui le crée et le sort sur la sortie standard.

Merci d'avance à quiconque pourra me mettre sur la voie.

Arbiel

P.S.
1) La documentation sed indique que la commande produit un résultat aléatoire si elle contient un caractère nul

This command allows one to pipe input from a shell command into pattern space. If a substitution was made, the command that is found in pattern space is executed and pattern space is replaced with its output. A trailing newline is suppressed; results are undefined if the command to be executed contains a nul character. This is a GNU sed extension.

Je ne sais pas exactement ce qu'il faut entendre par "if the command to be executed contains a nul character", mais j'ai vérifié que le fichier /tmp/skolios.n-skl-xml ne contient pas de caractères nuls.

2) la commande lit bien le fichier, la chaîne de caractères <n-skl/> ne se retrouve pas dans le fichier de sortie, de même que la fin de la ligne qui la contient.

3) une commande telle que

es "${gbl_xml}" | sed -r "\%<n-skl/>%r/tmp/skolios.n-skl.xml" 1>/tmp/skolios.xml

insère bien le fichier, mais ce n'est pas ce que je veux

Dernière modification par Arbiel (Le 16/05/2017, à 23:33)


Arbiel Perlacremaz
Dell Vostro 3550 Ubuntu 14.04 64 bits (je ne suis pas passé à la 16,04 à cause d'un problème majeur avec crypttab, et de sa déconcertante lenteur)
Protonmail, une messagerie sécurisée

Hors ligne

#2 Le 16/05/2017, à 07:30

le-peyo

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

¡ Holà !

Je pense qu'il manque le "-" devant ton argument e et je crois qu'il vaut mieux le placer juste après la commande sed pour plus de lisibilité.
Essaye avec ta commande comme ceci (c'est celle de ton post #1 modifiée):

es "${gbl_xml}" | sed -r -e "s|<n-skl/>|cat /tmp/skolios.n-skl.xml|" 1>/tmp/skolios.xml

À plus.

Dernière modification par le-peyo (Le 16/05/2017, à 07:38)


Sous Linux depuis 2009 | Packard Bell EasyNote TR 85
Windows 95 - XP - Vista | Ubuntu 09.04 | Ubuntu 10.04 LTS | Voyager 12.04 LTS 32 bits 64 bits | Voyager 14.04.4 LTS 64 bits + Switch Kwin
Lire du Flash... sans Flash... C'est par là =>

Hors ligne

#3 Le 16/05/2017, à 07:57

pingouinux

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

Bonjour Arbiel,
Tu devrais montrer le contenu de la variable "${gbl_xml}", ainsi que les résultats de

es "${gbl_xml}"

et

es "${gbl_xml}" | hd

@le-peyo : La syntaxe de la commande est valide (voir info sed)

Hors ligne

#4 Le 16/05/2017, à 08:28

le-peyo

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

pingouinux a écrit :

@le-peyo : La syntaxe de la commande est valide (voir info sed)

C'était une idée de piste à explorer car j'utilise un script (chez moi) où le "-e" est juste après le "sed" et qu' Arbiel avait un retour :

sh: 1: Syntax error: end of file unexpected

Malheureusement je connais très mal sed. Je ne peux aller plus loin.

Bon courage pour la suite.

Dernière modification par le-peyo (Le 16/05/2017, à 08:29)


Sous Linux depuis 2009 | Packard Bell EasyNote TR 85
Windows 95 - XP - Vista | Ubuntu 09.04 | Ubuntu 10.04 LTS | Voyager 12.04 LTS 32 bits 64 bits | Voyager 14.04.4 LTS 64 bits + Switch Kwin
Lire du Flash... sans Flash... C'est par là =>

Hors ligne

#5 Le 16/05/2017, à 10:57

Arbiel

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

Bonjour

@pingouinux

Et merci de te pencher sur mon problème. La variable gbl_xml contient un fichier xml assez long. J'en ai extrait une partie.

La fonction "es" est ici un simple "echo", et donne le contenu de gbl_xml

remi@remi-Vostro-3550:~$ es "${gbl_xml}"
<skl>
  <dossiers>
    <dossier idu="5f400a6d-9263-28ee-7e85-06c362efb177">/home/remi/Documents/Programmation/scripts bash
	<public type="clair"><archive date="2012-01-01">arbiel.perlacremaz@gmx.fr</archive></public>
	<fichiers/><n-skl/></dossier>
  </dossiers>
</skl>
remi@remi-Vostro-3550:~$

Il n'y a apparemment aucune valeur nulle dans le fichier, ce que je n'avais pas vérifié précédemment

remi@remi-Vostro-3550:~$ es "${gbl_xml}" | hd
00000000  3c 73 6b 6c 3e 0a 20 20  3c 64 6f 73 73 69 65 72  |<skl>.  <dossier|
00000010  73 3e 0a 20 20 20 20 3c  64 6f 73 73 69 65 72 20  |s>.    <dossier |
00000020  69 64 75 3d 22 35 66 34  30 30 61 36 64 2d 39 32  |idu="5f400a6d-92|
00000030  36 33 2d 32 38 65 65 2d  37 65 38 35 2d 30 36 63  |63-28ee-7e85-06c|
00000040  33 36 32 65 66 62 31 37  37 22 3e 2f 68 6f 6d 65  |362efb177">/home|
00000050  2f 72 65 6d 69 2f 44 6f  63 75 6d 65 6e 74 73 2f  |/remi/Documents/|
00000060  50 72 6f 67 72 61 6d 6d  61 74 69 6f 6e 2f 73 63  |Programmation/sc|
00000070  72 69 70 74 73 20 62 61  73 68 0a 09 3c 70 75 62  |ripts bash..<pub|
00000080  6c 69 63 20 74 79 70 65  3d 22 63 6c 61 69 72 22  |lic type="clair"|
00000090  3e 3c 61 72 63 68 69 76  65 20 64 61 74 65 3d 22  |><archive date="|
000000a0  32 30 31 32 2d 30 31 2d  30 31 22 3e 61 72 62 69  |2012-01-01">arbi|
000000b0  65 6c 2e 70 65 72 6c 61  63 72 65 6d 61 7a 40 67  |el.perlacremaz@g|
000000c0  6d 78 2e 66 72 3c 2f 61  72 63 68 69 76 65 3e 3c  |mx.fr</archive><|
000000d0  2f 70 75 62 6c 69 63 3e  0a 09 3c 66 69 63 68 69  |/public>..<fichi|
000000e0  65 72 73 2f 3e 3c 6e 2d  73 6b 6c 2f 3e 3c 2f 64  |ers/><n-skl/></d|
000000f0  6f 73 73 69 65 72 3e 0a  20 20 3c 2f 64 6f 73 73  |ossier>.  </doss|
00000100  69 65 72 73 3e 0a 3c 2f  73 6b 6c 3e 0a           |iers>.</skl>.|
0000010d
remi@remi-Vostro-3550:~$ 

J'ai également réduit la taille du fichier tmp/skolios.n-skl.xml (es est ici un cat)

remi@remi-Vostro-3550:~$ es /tmp/skolios.n-skl.xml
<fichier idu="17501ad9-65f0-c0df-59f2-d8c9afae958e" date="2017-05-16 10:13:10+02:00">/home/remi/Documents/Programmation/scripts bash/wifi.sh<relatif>wifi.sh</relatif><droits>775 # -rwxrwxr-x</droits><proprio>1000 # remi</proprio><groupe>0 # root</groupe><taille>866</taille><sig type="md5" source="fichier">a6b179c3-8f32-f8f7-1353-354d3fea30d2</sig></fichier>
remi@remi-Vostro-3550:~$ 

qui ne contient aucun octet nul

remi@remi-Vostro-3550:~$ hd /tmp/skolios.n-skl.xml
00000000  3c 66 69 63 68 69 65 72  20 69 64 75 3d 22 31 37  |<fichier idu="17|
00000010  35 30 31 61 64 39 2d 36  35 66 30 2d 63 30 64 66  |501ad9-65f0-c0df|
00000020  2d 35 39 66 32 2d 64 38  63 39 61 66 61 65 39 35  |-59f2-d8c9afae95|
00000030  38 65 22 20 64 61 74 65  3d 22 32 30 31 37 2d 30  |8e" date="2017-0|
00000040  35 2d 31 36 20 31 30 3a  31 33 3a 31 30 2b 30 32  |5-16 10:13:10+02|
00000050  3a 30 30 22 3e 2f 68 6f  6d 65 2f 72 65 6d 69 2f  |:00">/home/remi/|
00000060  44 6f 63 75 6d 65 6e 74  73 2f 50 72 6f 67 72 61  |Documents/Progra|
00000070  6d 6d 61 74 69 6f 6e 2f  73 63 72 69 70 74 73 20  |mmation/scripts |
00000080  62 61 73 68 2f 77 69 66  69 2e 73 68 3c 72 65 6c  |bash/wifi.sh<rel|
00000090  61 74 69 66 3e 77 69 66  69 2e 73 68 3c 2f 72 65  |atif>wifi.sh</re|
000000a0  6c 61 74 69 66 3e 3c 64  72 6f 69 74 73 3e 37 37  |latif><droits>77|
000000b0  35 20 23 20 2d 72 77 78  72 77 78 72 2d 78 3c 2f  |5 # -rwxrwxr-x</|
000000c0  64 72 6f 69 74 73 3e 3c  70 72 6f 70 72 69 6f 3e  |droits><proprio>|
000000d0  31 30 30 30 20 23 20 72  65 6d 69 3c 2f 70 72 6f  |1000 # remi</pro|
000000e0  70 72 69 6f 3e 3c 67 72  6f 75 70 65 3e 30 20 23  |prio><groupe>0 #|
000000f0  20 72 6f 6f 74 3c 2f 67  72 6f 75 70 65 3e 3c 74  | root</groupe><t|
00000100  61 69 6c 6c 65 3e 38 36  36 3c 2f 74 61 69 6c 6c  |aille>866</taill|
00000110  65 3e 3c 73 69 67 20 74  79 70 65 3d 22 6d 64 35  |e><sig type="md5|
00000120  22 20 73 6f 75 72 63 65  3d 22 66 69 63 68 69 65  |" source="fichie|
00000130  72 22 3e 61 36 62 31 37  39 63 33 2d 38 66 33 32  |r">a6b179c3-8f32|
00000140  2d 66 38 66 37 2d 31 33  35 33 2d 33 35 34 64 33  |-f8f7-1353-354d3|
00000150  66 65 61 33 30 64 32 3c  2f 73 69 67 3e 3c 2f 66  |fea30d2</sig></f|
00000160  69 63 68 69 65 72 3e 0a                           |ichier>.|
00000168
remi@remi-Vostro-3550:~$ 

Compte tenu de la présence de " dans le fichier à inclure, j'ai encadré la commande s pas des '.
Tout ceci me donne le même résultat

remi@remi-Vostro-3550:~$ es "${gbl_xml}" | sed -r 's|<n-skl/>|cat /tmp/skolios.n-skl.xml|e' 1>/tmp/skolios.xml
sh: 1: Syntax error: end of file unexpected
remi@remi-Vostro-3550:~$ 

Arbiel


Arbiel Perlacremaz
Dell Vostro 3550 Ubuntu 14.04 64 bits (je ne suis pas passé à la 16,04 à cause d'un problème majeur avec crypttab, et de sa déconcertante lenteur)
Protonmail, une messagerie sécurisée

Hors ligne

#6 Le 16/05/2017, à 12:39

pingouinux

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

J'ai repris ton premier exemple en #5. En fait, tu essayes d'exécuter cette commande

	<fichiers/>cat /tmp/skolios.n-skl.xml</dossier>

Essaye plutôt ceci

es "${gbl_xml}" | sed -r 's|.*<n-skl/>.*|cat /tmp/skolios.n-skl.xml|e' 1>/tmp/skolios.xml

Hors ligne

#7 Le 16/05/2017, à 15:49

Arbiel

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

Je vais effectivement essayer de contourner le problème en faisant en sorte la ligne ne contienne rien d'autre que <n-skl/>; mais alors, je pencherais plutôt vers une solution fondée sur le 3e post-scriptum du #1, c'est-à-dire

es "${gbl_xml}" | sed -r "\%<n-skl/>%{d;r/tmp/skolios.n-skl.xml}" 1>/tmp/skolios.xml

Comme je n'ai pas le temps de tester à l'instant, dis-moi, s'il te plaît, si elle te paraît correcte.

Je pense que je suis tombé sur un bug de sed. Mais avant de faire un rapport, je vais tester la dernière version qui est la 4.4 du 3 févier 2017 alors que j'utilise actuellement la 4.2.2

remi@remi-Vostro-3550:~$ sed --version
sed (GNU sed) 4.2.2
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Jay Fenlason, Tom Lord, Ken Pizzini,
and Paolo Bonzini.
Page de GNU sed: <http://www.gnu.org/software/sed/>.
Aide générale pour utiliser les logiciels GNU: <http://www.gnu.org/help/gethelp.fr.html>.
Rapporter toutes anomalies à: <bug-sed@gnu.org>.
N'oubliez pas d'inclure le mot ``sed'' quelque-part dans la zone ``Subject:''.
remi@remi-Vostro-3550:~$ 

Je rendrai compte ici de la suite.

Arbiel


Arbiel Perlacremaz
Dell Vostro 3550 Ubuntu 14.04 64 bits (je ne suis pas passé à la 16,04 à cause d'un problème majeur avec crypttab, et de sa déconcertante lenteur)
Protonmail, une messagerie sécurisée

Hors ligne

#8 Le 16/05/2017, à 16:49

pingouinux

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

Après essais, je ferais plutôt ceci (si j'ai bien compris ce que tu veux) :

es "${gbl_xml}" | sed -r "\%<n-skl/>%{r/tmp/skolios.n-skl.xml
d}" 1>/tmp/skolios.xml

Le problème initial ne me paraît pas un bug, mais une mauvaise utilisation de sed.

Hors ligne

#9 Le 16/05/2017, à 21:12

Arbiel

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

Il semble bien que ce soit un bug de sed

remi@remi-Vostro-3550:~$ echo -e "b \n<négatif/>\nc" | sed -r 's|<négatif/>|echo "<positif/>"|e'
b 
<positif/>
c
remi@remi-Vostro-3550:~$ echo -e "<fichiers/><négatif/></dossier>" | sed -r 's|<négatif/>|echo "<positif/>"|e'
sh: 1: Syntax error: end of file unexpected

remi@remi-Vostro-3550:~$ 

Pour contourner mon problème, j'ai besoin de transformer
<fichiers/><négatif/></dossier> en 3 lignes, mais je ne parviens pas à introduire des passages à la ligne à la bonne place.


Arbiel Perlacremaz
Dell Vostro 3550 Ubuntu 14.04 64 bits (je ne suis pas passé à la 16,04 à cause d'un problème majeur avec crypttab, et de sa déconcertante lenteur)
Protonmail, une messagerie sécurisée

Hors ligne

#10 Le 16/05/2017, à 21:28

pingouinux

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

Ce n'est pas un bug. Ton sed plante parce qu'il essaye d'exécuter cette commande

<fichiers/>echo "<positif/>"</dossier>

qui donne évidemment une erreur de syntaxe.

$ echo -e "<fichiers/><négatif/></dossier>" | sed -r 's|(.*)<négatif/>(.*)|\1\n<positif/>\n\2|'
<fichiers/>
<positif/>
</dossier>

Hors ligne

#11 Le 16/05/2017, à 23:01

Arbiel

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

La documentation n'est pas vraiment claire

e
    This command allows one to pipe input from a shell command into pattern space. If a substitution was made, the command that is found in pattern space is executed and pattern space is replaced with its output.

Le fait qu'il y a d'abord substitution puis exécution de la commande ainsi constituée n'est pas évident, même si cela peut paraître logique lorsque l'on a enfin compris.

J'ai essayé

es "${gbl_xml}" | sed -r "\%<n-skl/>%s|^(.*)<n-skl/>(.*)$|echo -n "\1" && cat /tmp/skolios.n-skl.xml && echo -n "\2"|e" 1>/tmp/skolios.xml

mais ça ne marche pas mieux.

Je modifie mon script pour charger le contenu du fichier dans la variable xml, puis

es "${gbl_xml}" | sed -r "\%<n-skl/>%s|^(.*)<n-skl/>(.*)$|\1${xml}\2|" 1>/tmp/skolios.xml

qui fonctionne, pour le moins, qui vient de fonctionner dans le test que j'ai fait.

Mais le second test que je viens de faire ne fonctionne pas ; dans le premier test, mon fichier ne contenait qu'une seule ligne. Je vais donc revenir à la solution qui consiste à couper la ligne en 3 parties, comme tu m'as indiqué, puis à insérer le contenu du fichier à la place de la seconde ligne par la commande de substitution.

Merci encore pour ton aide précieuse, sans laquelle je n'aurais pas pu aboutir

Arbiel

Dernière modification par Arbiel (Le 16/05/2017, à 23:28)


Arbiel Perlacremaz
Dell Vostro 3550 Ubuntu 14.04 64 bits (je ne suis pas passé à la 16,04 à cause d'un problème majeur avec crypttab, et de sa déconcertante lenteur)
Protonmail, une messagerie sécurisée

Hors ligne

#12 Le 17/05/2017, à 07:08

pingouinux

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

Remplace ta première commande en #11

es "${gbl_xml}" | sed -r "\%<n-skl/>%s|^(.*)<n-skl/>(.*)$|echo -n "\1" && cat /tmp/skolios.n-skl.xml && echo -n "\2"|e" 1>/tmp/skolios.xml

par

es "${gbl_xml}" | sed -r "\%<n-skl/>%s|^(.*)<n-skl/>(.*)$|echo -n \"\1\" \&\& cat /tmp/skolios.n-skl.xml \&\& echo -n \"\2\"|e" 1>/tmp/skolios.xml

Édité :
python se prête très bien à ce genre d'opération.

$ cat inclusion.py
#!/usr/bin/env python3
import sys
fic_init      = sys.argv[1]
fic_a_inclure = sys.argv[2]
fic_out       = sys.argv[3]

with open(fic_init,'r') as f: txt_init=f.read()
with open(fic_a_inclure,'r') as f: txt_a_inclure=f.read()

txt_out=txt_init.replace('<n-skl/>',txt_a_inclure)

with open(fic_out,'w') as f: f.write(txt_out)

À appeler ainsi :

./inclusion.py fichier_a_lire /tmp/skolios.n-skl.xml /tmp/skolios.xml

Dernière modification par pingouinux (Le 17/05/2017, à 07:40)

Hors ligne

#13 Le 17/05/2017, à 18:14

Arbiel

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

Bonsoir

Je ne connais pas du tout python, mais le code est suffisamment explicite pour que tout soit clair, sauf la première ligne

$ cat inclusion.py

Je vais essayer de me plonger dans python car il en est souvent question ici.

Sais-tu si la manipulation des fichiers xml y est aisée ? En bash, j'utilise xmlstarlet, mais cet outil n'est pas très pratique car il fonctionne ligne par ligne, je veux dire par là que l'accès à la moindre donnée nécessite la lecture et l'analyse de l'intégralité du fichier dans lequel elle se trouve. On peut bien évidemment restreindre le fichier à un nœud xml, mais cela n'enlève rien à la lourdeur de l'outil.

Arbiel


Arbiel Perlacremaz
Dell Vostro 3550 Ubuntu 14.04 64 bits (je ne suis pas passé à la 16,04 à cause d'un problème majeur avec crypttab, et de sa déconcertante lenteur)
Protonmail, une messagerie sécurisée

Hors ligne

#14 Le 17/05/2017, à 18:22

pingouinux

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

mais le code est suffisamment explicite pour que tout soit clair, sauf la première ligne

$ cat inclusion.py

J'ai appelé le script inclusion.py, et cette ligne est la commande qui liste le le fichier, précédée du prompt.

Il existe des modules pour traiter spécifiquement les fichiers .xml, mais je n'ai jamais pratiqué. Il y a des spécialistes sur le forum qui pourront t'aiguiller.

Hors ligne

#15 Le 17/05/2017, à 19:44

Arbiel

Re : [Résolu] sed : substitution d'une chaîne de caractères par un fichier

Désolé, j'ai cru que c'était un ordre python. J'aurais dû comprendre sans te solliciter.


Arbiel Perlacremaz
Dell Vostro 3550 Ubuntu 14.04 64 bits (je ne suis pas passé à la 16,04 à cause d'un problème majeur avec crypttab, et de sa déconcertante lenteur)
Protonmail, une messagerie sécurisée

Hors ligne