Contenu | Rechercher | Menus

Annonce

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.

À propos de l'équipe du forum.

#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 hmm 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]

Aube DuKaos a écrit :

Bonjour,
Je ne comprend pas ton pb hmm 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  smile

Hors ligne

#5 Le 18/11/2011, à 10:35

Aube DuKaos

Re : Remplacer texte à partir de la ligne X [RESOLU]

Miroslav a écrit :

C'est une solution en mode console que je cherche, pour un script

La sourie fonctionne sur les console tongue

Oui, je sais, je sort... roll


"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]

Miroslav a écrit :

En tout cas, merci

de rien, si je peux être totalement inutile n'hésite pas tongue


"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,

pingouinux a écrit :
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 !)

Fonctionne pas a écrit :
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]

Postmortem #11 a écrit :

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]

pingouinux a écrit :

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]

pingouinux a écrit :

@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 !! tongue
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]

man bash a écrit :

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]

Postmortem #23 a écrit :
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