#1 Le 18/11/2011, à 10:04
- Miroslav
Remplacer texte à partir de la ligne X [RESOLU]
Bonjour,
J'ai deux fichiers textes, je souhaiterais copier le texte d'un fichier source à partir de la ligne 4 et remplacer le texte dans le fichier cible à partir de la ligne 4. J'ai regardé du coté de head / sed mais je ne m'en sort pas...
D'avance merci
Dernière modification par Miroslav (Le 18/11/2011, à 11:36)
Hors ligne
#2 Le 18/11/2011, à 10:20
- pingouinux
Re : Remplacer texte à partir de la ligne X [RESOLU]
Bonjour,
Voici une méthode bestiale :
head -3 cible >resul
tail -n +4 source >>resul
mv resul cible
ou
cat <(head -3 cible) <(tail -n +4 source) >resul
mv resul cible
Dernière modification par pingouinux (Le 18/11/2011, à 10:23)
Hors ligne
#3 Le 18/11/2011, à 10:24
- Aube DuKaos
Re : Remplacer texte à partir de la ligne X [RESOLU]
Bonjour,
Je ne comprend pas ton pb d'ou tu veux copier et ou tu veux le copier? Le mode "insérer" (touche "Inser" de ton clavier) ne fonctionne pas? Autre solution: copier les deux texte dans un éditeur de texte, faire ta manipe et tous recopier la ou tu le veux.
"Les contes de fées ne révèlent pas aux enfants que les dragons existent, les enfants le savent déjà. Les contes de fées révèlent aux enfants qu'on peut tuer ces dragons."
G.K. Chesterton
Hors ligne
#4 Le 18/11/2011, à 10:33
- Miroslav
Re : Remplacer texte à partir de la ligne X [RESOLU]
Bonjour,
Je ne comprend pas ton pb d'ou tu veux copier et ou tu veux le copier? Le mode "insérer" (touche "Inser" de ton clavier) ne fonctionne pas? Autre solution: copier les deux texte dans un éditeur de texte, faire ta manipe et tous recopier la ou tu le veux.
C'est une solution en mode console que je cherche, pour un script
pingouinux: Merci, je vais la jouer bestiale je pense dans un premier temps
Hors ligne
#5 Le 18/11/2011, à 10:35
- Aube DuKaos
Re : Remplacer texte à partir de la ligne X [RESOLU]
C'est une solution en mode console que je cherche, pour un script
La sourie fonctionne sur les console
Oui, je sais, je sort...
"Les contes de fées ne révèlent pas aux enfants que les dragons existent, les enfants le savent déjà. Les contes de fées révèlent aux enfants qu'on peut tuer ces dragons."
G.K. Chesterton
Hors ligne
#6 Le 18/11/2011, à 10:54
- pingouinux
Re : Remplacer texte à partir de la ligne X [RESOLU]
Voici une autre méthode (peut-être sauvegarder cible avant, par prudence) :
sed -ni '1,3p' cible
tail -n +4 source >>cible
ou
sed -ni '1,3p' cible
sed -n '4,$p' source >>cible
Dernière modification par pingouinux (Le 18/11/2011, à 11:01)
Hors ligne
#7 Le 18/11/2011, à 11:23
- Watael
Re : Remplacer texte à partir de la ligne X [RESOLU]
salut,
en un seul coup de awk
awk -v lignes=5 '(NR == lignes){nextfile}; (NR < lignes || NR >= lignes*2)' cible source
Connected \o/
Welcome to sHell. · eval is evil.
Hors ligne
#8 Le 18/11/2011, à 11:35
- Miroslav
Re : Remplacer texte à partir de la ligne X [RESOLU]
j'ai opté pour la solution de sed sans sauvegarde, j'ai fait des tests avec des fichiers à la con et ça marche super bien
j'avoue qu'au vu de mon niveau pour tout ce qui concerne la console, la syntaxe de awk est super flipante, même si je ne doute pas un instant de son efficacité. En tout cas, merci
Hors ligne
#9 Le 18/11/2011, à 11:40
- Aube DuKaos
Re : Remplacer texte à partir de la ligne X [RESOLU]
En tout cas, merci
de rien, si je peux être totalement inutile n'hésite pas
"Les contes de fées ne révèlent pas aux enfants que les dragons existent, les enfants le savent déjà. Les contes de fées révèlent aux enfants qu'on peut tuer ces dragons."
G.K. Chesterton
Hors ligne
#10 Le 18/11/2011, à 11:40
- pingouinux
Re : Remplacer texte à partir de la ligne X [RESOLU]
@Watael #7
Joli !
On peut même simplifier un poil, en utilisant FNR :
awk -v lignes=4 '(NR == lignes){nextfile}; (NR < lignes || FNR >= lignes)' cible source
Hors ligne
#11 Le 18/11/2011, à 12:16
- Postmortem
Re : Remplacer texte à partir de la ligne X [RESOLU]
Salut,
cat <(head -3 cible) <(tail -n +4 source) >resul mv resul cible
Tu peux rediriger direct dans cible, ça fonctionne :
Edit : en fait non, ça fonctionne pas ! (enfin aléatoirement !)
cat <(head -3 cible) <(tail -n +4 source) > cible
@Watael, c'est bien vu le coup du awk, je le note dans un coin, merci !
Moi j'étais entrain d'essayer de faire ça en un seul sed mais je renonce, j'ai plus de cheveux à m'arracher ! (Puis faut que je bosse un peu !)
Dernière modification par Postmortem (Le 22/11/2011, à 14:22)
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne
#12 Le 18/11/2011, à 13:27
- pingouinux
Re : Remplacer texte à partir de la ligne X [RESOLU]
Tu peux rediriger direct dans cible, ça fonctionne :
cat <(head -3 cible) <(tail -n +4 source) > cible
Je viens d'essayer, et ça ne marche pas chez moi ???
$ cat source
1
2
3
4
5
6
$ cat cible
a
b
c
d
e
f
g
$ cat <(head -3 cible) <(tail -n +4 source) > cible
$ cat cible
4
5
6
Dernière modification par pingouinux (Le 18/11/2011, à 13:28)
Hors ligne
#13 Le 18/11/2011, à 14:36
- Postmortem
Re : Remplacer texte à partir de la ligne X [RESOLU]
Je viens d'essayer, et ça ne marche pas chez moi ???
Euh...... Ben ça marche pas chez moi non plus !!!
Je ressaierai au taf tout à l'heure... J'avais peut-être pas les yeux en face des trous !
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne
#14 Le 18/11/2011, à 15:32
- Postmortem
Re : Remplacer texte à partir de la ligne X [RESOLU]
Aaaaaahhhhh !! Je ne suis pas fou !!
$ more *
::::::::::::::
cible
::::::::::::::
a
b
c
d
e
f
g
::::::::::::::
source
::::::::::::::
1
2
3
4
5
6
$ cat <(head -3 cible) <(tail -n +4 source) > cible
$ cat cible
a
b
c
4
5
6
$ bash --version
GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2005 Free Software Foundation, Inc.
$ uname -a
Linux XXXXXXXXXXXX 2.6.18-164.el5 #1 SMP Tue Aug 18 15:51:48 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
Edit : du coup, le fonctionnement normal, c'est lequel ? Celui d'Ubuntu ou celui du Red Hat qu'on a au taf ??
Dernière modification par Postmortem (Le 18/11/2011, à 15:51)
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne
#15 Le 18/11/2011, à 15:59
- pingouinux
Re : Remplacer texte à partir de la ligne X [RESOLU]
@Postmortem #14 :
On a des versions différentes de bash et du noyau.
Pour moi, on ne pouvait pas rediriger une commande sur un fichier utilisé en entrée, mais les choses peuvent avoir évolué. Dans le doute, je préfère jouer la prudence et m'abstenir.
$ bash --version
GNU bash, version 4.2.8(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
$ uname -a
Linux XXXXXXXX 2.6.38-13-generic #52-Ubuntu SMP Tue Nov 8 16:53:51 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux
Hors ligne
#16 Le 19/11/2011, à 12:36
- Postmortem
Re : Remplacer texte à partir de la ligne X [RESOLU]
Salut !
Y'a aussi moyen de faire sans passer par un fichier temporaire sur Ubuntu :
Edit : en fait, ça ne fonctionne pas :
$ more *
::::::::::::::
cible
::::::::::::::
a
b
c
d
e
f
g
::::::::::::::
source
::::::::::::::
1
2
3
4
5
6
$ cat <(head -3 cible) <(tail -n +4 source) > >(cat > cible)
$ cat cible
a
b
c
4
5
6
Si quelqu'un a l'explication de la différence de fonctionnement entre Red Hat et Ubuntu (ou les 2 versions de bash) ??
Et si quelqu'un a une explication sur le pourquoi du comment on peut utiliser le même fichier en entrée et en sortie avec la substitution de processus ?? Parce que j'ai beau lire différentes docs, ce n'est pas très clair dans ma tête !
Dernière modification par Postmortem (Le 22/11/2011, à 14:23)
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne
#17 Le 19/11/2011, à 13:32
- pingouinux
Re : Remplacer texte à partir de la ligne X [RESOLU]
@Postmortem : Je vois que tu es tenace...
Je n'ai pas de réponse, mais voici de quoi te creuser encore les méninges.
Après quelques tests avec ta dernière commande, j'obtiens 3 résultats différents de manière aléatoire, le bon étant le plus fréquent. Voici la boucle :
for i in {1..1000}; do cp src source; cp cib cible; cat <(head -3 cible) <(tail -n +4 source) > >(cat > cible); mv cible cible.$i; done
Évidemment, source et cible sont réinitialisés entre chaque test :
$# Résultat obtenu 880 fois / 1000
a
b
c
4
5
6
$# Résultat obtenu 118 fois / 1000
4
5
6
$# Résultat obtenu 2 fois / 1000
a
b
c
d
e
f
g
Hors ligne
#18 Le 19/11/2011, à 13:52
- Postmortem
Re : Remplacer texte à partir de la ligne X [RESOLU]
@Postmortem : Je vois que tu es tenace...
D'habitude, on me dit plutôt que je suis têtu, ou une bourrique ! Suis du Kreiz Breizh (centre Bretagne), c'est dans mes gênes !!
Enfin, j'aime bien comprendre ce qu'il se passe et quand je comprends pas, ça me turlupine !
Je te remercie donc de tes tests qui font que maintenant, ça me turlupine encore plus !!
C'est quand même dingue que le résultat diffère...
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne
#19 Le 19/11/2011, à 15:07
- aduxas
Re : Remplacer texte à partir de la ligne X [RESOLU]
Process substitution is supported on systems that support named pipes (FIFOs) or the /dev/fd method of naming open files. It takes the form of <(list) or >(list). The process list is run with its input or output connected to a FIFO or some file in /dev/fd. The name of this file is passed as an argument to the current command as the result of the expansion.
Je ne sais pas mais si tu lances plusieurs process en même temps ("process substitution") et tu les connectes avec des pipes (first-in first-out), est-ce vraiment une procédure déterministe?
EDIT: j'ai fait deux essais manuels; le deuxième donnait le résultat espéré, mais le premier donnait
4
5
6
Dernière modification par aduxas (Le 19/11/2011, à 15:14)
Hors ligne
#20 Le 20/11/2011, à 10:41
- Postmortem
Re : Remplacer texte à partir de la ligne X [RESOLU]
Bonjour et bon dimanche !
Ah, je crois avoir compris : toutes les substitution de processus s'exécutent en même temps ou presque ; ce qui fait que si >(cat > cible) débute un p'tit peu avant <(head -3 cible), ben le head ne renvoie rien... C'est bien ça docteur ?!
Moi je les voyais s’exécuter dans leur ordre d'apparition.
Merci à aduxas et pingouinux pour les éclaircissements !
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne
#21 Le 20/11/2011, à 15:03
- aduxas
Re : Remplacer texte à partir de la ligne X [RESOLU]
Oui, c'est cela. Je serais curieux de savoir si tes statistiques donnent autant ou moins de variation sur un processeur mono-coeur.
Hors ligne
#22 Le 20/11/2011, à 20:36
- pingouinux
Re : Remplacer texte à partir de la ligne X [RESOLU]
Allez, un dernier test (peut-être "légèrement" hors-sujet...), mais le mystère ne s'éclaircit pas.
Je voulais trier les résultats en me servant du md5sum du fichier cible. Le tableau associatif N compte le nombre d'occurences de chaque md5sum calculé, ce dernier servant à suffixer le nom du fichier cible.
Quand le calcul suivant est fait :
cat <(head -3 cible) <(tail -n +4 source) > >(cat > cible)
md5=$(md5sum cible|cut -d" " -f1)
md5 semble, dans certains cas, calculé AVANT que cible ne soit mis à jour par la 1ère commande.
Mon script :
#!/bin/bash
cat >src <<EOF
1
2
3
4
5
6
EOF
cat >cib <<EOF
a
b
c
d
e
f
g
EOF
declare -A N
M=$1
for i in $(seq 1 $M)
do
cp src source; cp cib cible;
cat <(head -3 cible) <(tail -n +4 source) > >(cat > cible)
md5=$(md5sum cible|cut -d" " -f1)
if [[ -z "${N[$md5]}" ]]; then
cp cible cible.$md5
echo $n cible.$md5 copié
fi
((N[$md5]++))
done
for md5 in ${!N[*]}
do
printf "%s %4d fois / %4d\n" $md5 ${N[$md5]} $i
cat cible.$md5
done
md5sum cib cible.* /dev/null | sort
Les résultats (quelques commentaires ajoutés) :
cible.620b0551911889dae3c0733108f44f72 copié
cible.d41d8cd98f00b204e9800998ecf8427e copié
cible.47d69c01abdea0f776cbc9e788b5186f copié
cible.40c53c58fdafacc83cfff6ee3d2f6d69 copié
cible.b0e896150b751660e75581da1389c150 copié
cible.a9b63671334080e791ff647a4b0881f7 copié
a9b63671334080e791ff647a4b0881f7 3 fois / 100000 # md5sum cohérent, réponse erronée
4
5
6
4
5
6
40c53c58fdafacc83cfff6ee3d2f6d69 3 fois / 100000 # md5sum cohérent, réponse erronée
a
b
c
620b0551911889dae3c0733108f44f72 91153 fois / 100000 # md5sum cohérent, bonne réponse
a
b
c
4
5
6
d41d8cd98f00b204e9800998ecf8427e 544 fois / 100000 # md5sum de /dev/null, bonne réponse
a
b
c
4
5
6
47d69c01abdea0f776cbc9e788b5186f 8256 fois / 100000 # md5sum cohérent, réponse erronée
4
5
6
b0e896150b751660e75581da1389c150 41 fois / 100000 # md5sum de cible de départ, bonne réponse
a
b
c
4
5
6
40c53c58fdafacc83cfff6ee3d2f6d69 cible.40c53c58fdafacc83cfff6ee3d2f6d69
47d69c01abdea0f776cbc9e788b5186f cible.47d69c01abdea0f776cbc9e788b5186f
620b0551911889dae3c0733108f44f72 cible.620b0551911889dae3c0733108f44f72
620b0551911889dae3c0733108f44f72 cible.b0e896150b751660e75581da1389c150
620b0551911889dae3c0733108f44f72 cible.d41d8cd98f00b204e9800998ecf8427e
a9b63671334080e791ff647a4b0881f7 cible.a9b63671334080e791ff647a4b0881f7
b0e896150b751660e75581da1389c150 cib
d41d8cd98f00b204e9800998ecf8427e /dev/null
Hors ligne
#23 Le 21/11/2011, à 16:24
- Postmortem
Re : Remplacer texte à partir de la ligne X [RESOLU]
Salut,
Je viens de tester ce que ça donne sur Red Hat au taf avec le script de pingouinux ; voilà le résultat :
cible.620b0551911889dae3c0733108f44f72 copié
cible.47d69c01abdea0f776cbc9e788b5186f copié
cible.40c53c58fdafacc83cfff6ee3d2f6d69 copié
cible.d41d8cd98f00b204e9800998ecf8427e copié
620b0551911889dae3c0733108f44f72 93717 fois / 100000 # md5sum cohérent, bonne réponse
a
b
c
4
5
6
47d69c01abdea0f776cbc9e788b5186f 6261 fois / 100000 # md5sum cohérent, réponse erronée
4
5
6
40c53c58fdafacc83cfff6ee3d2f6d69 2 fois / 100000 # md5sum venant d'une autre planète, bonne réponse
a
b
c
4
5
6
d41d8cd98f00b204e9800998ecf8427e 20 fois / 100000 # md5sum de /dev/null, bonne réponse
a
b
c
4
5
6
47d69c01abdea0f776cbc9e788b5186f cible.47d69c01abdea0f776cbc9e788b5186f
51196a4299942b14b7543f8143accb77 test.sh
620b0551911889dae3c0733108f44f72 cible
620b0551911889dae3c0733108f44f72 cible.40c53c58fdafacc83cfff6ee3d2f6d69
620b0551911889dae3c0733108f44f72 cible.620b0551911889dae3c0733108f44f72
620b0551911889dae3c0733108f44f72 cible.d41d8cd98f00b204e9800998ecf8427e
b0e896150b751660e75581da1389c150 cib
d41d8cd98f00b204e9800998ecf8427e /dev/null
f3a4562cd2134c76b4ff170ce6f28fee source
f3a4562cd2134c76b4ff170ce6f28fee src
Edit : le md5sum venant d'une autre planète correspond à la somme d'un fichier que pingouinux avait obtenu :
$ cat fic
a
b
c
$ md5sum fic
40c53c58fdafacc83cfff6ee3d2f6d69 fic
Dernière modification par Postmortem (Le 21/11/2011, à 16:39)
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne
#24 Le 21/11/2011, à 16:44
- pingouinux
Re : Remplacer texte à partir de la ligne X [RESOLU]
40c53c58fdafacc83cfff6ee3d2f6d69 2 fois / 100000 # md5sum venant d'une autre planète, bonne réponse
Peut-être pas de si loin...
$ cat fichier.extra-terrestre
a
b
c
$ md5sum fichier.extra-terrestre
40c53c58fdafacc83cfff6ee3d2f6d69 fichier.extra-terrestre
Hors ligne
#25 Le 21/11/2011, à 17:48
- Postmortem
Re : Remplacer texte à partir de la ligne X [RESOLU]
@pingouinux : oui j'avais vu, j'avais édité mon post just'avant que tu écrives.
Sinon, j'ai refait des tests sur la Red Hat du taf en remplaçant la redirection > >(cat > cible) par > cible et là, je n'obtiens plus de md5 incohérent. Mais le résultat est toujours aléatoire :
cible.620b0551911889dae3c0733108f44f72 copié
cible.47d69c01abdea0f776cbc9e788b5186f copié
620b0551911889dae3c0733108f44f72 85691 fois / 100000
a
b
c
4
5
6
47d69c01abdea0f776cbc9e788b5186f 14309 fois / 100000
4
5
6
Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »
Hors ligne