#1 Le 27/07/2012, à 16:39
- natacha123
script lecture et écriture fichier
Bonjour à tous, je suis débutante en script, à vrai dire je ne connais quasiment rien du tout.
J'aimerai faire un truc tout simple :
J'ai deux fichiers, pour simplifier fichierA et fichierB, les deux contiennent une liste d'entiers.
fichierA contient des entiers de fichierB.
Je veux remplacer tous les entiers de fichierA égaux aux entiers de fichierB par -1.
Merci d'avance à tous ceux qui pourront m'éclairer
Hors ligne
#2 Le 27/07/2012, à 17:03
- Bousky
Re : script lecture et écriture fichier
En supposant que fichierA et fichierB sont de la forme
1
23
12
10
ça devrait marcher :
mv fichierA fichierA.old;while read i;do grep -xq $i fichierB&&echo -1||echo $i;done<fichierA.old>fichierA
Dernière modification par Bousky (Le 27/07/2012, à 17:06)
Linux qui plante complètement ? Plus rien ne répond ? On peut toujours le redémarrer proprement :
Alt + SysRq + REISUB (Retourne En Islande Sur Un Bateau !)
Hors ligne
#3 Le 27/07/2012, à 18:41
- nesthib
Re : script lecture et écriture fichier
@natacha123 : pourrais tu donner un exemple des fichiers de départ et du fichier de sortie ? La question est pour le moment ambiguë… on ne sait pas si tu veux faire une substitution ligne à ligne ou si l'ordre de nombres contenus dans fichierA n'importe pas.
si l'ordre n'importe pas (i.e. tous les nombres contenus dans A seront remplacés, quelle que soit la ligne) :
NUMBERS=$(sed '$!{:a;N;s/\n/\\|/;ta}' fichierA)
sed "s/^\($NUMBERS\)$/-1/" fichierB
NB. il faut ajouter l'option -i à sed dans le seconde commande pour modifier le fichier en place. Comme il n'est pas non plus clair quel fichier doit être modifié, dans mon exemple fichier A est la référence et fichierB est modifié, ce qui donne :
fichierA :
1
3
5
fichierB avant substitution :
1
2
3
4
5
fichierB après substitution :
-1
2
-1
4
-1
Si la comparaison a lieu ligne à ligne :
while read a b ; do [[ $a == $b ]] && echo -1 || echo $b ; done < <(paste fichierA fichierB)
fichierA :
1
3
3
4
4
fichier B :
1
2
3
4
5
sortie :
-1
2
-1
4
-1
edit : j'ai ajouté des exemples
Dernière modification par nesthib (Le 27/07/2012, à 19:45)
GUL Bordeaux : Giroll – Services libres : TdCT.org
Hide in your shell, scripts & astuces : applications dans un tunnel – smart wget – trouver des pdf – install. auto de paquets – sauvegarde auto – ♥ awk
⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn
Hors ligne
#4 Le 30/07/2012, à 10:52
- natacha123
Re : script lecture et écriture fichier
Bonjour à tous,
Je vous remercie beaucoup pour vos réponses.
Je vais préciser un peu mon problème:
le fichierA contient à peu près 100 000 lignes avec 5 colonnes comme suit:
94518 4 1 53021 45 5239 55645 2 16001 21020 46996 57444 3 40069 32257 21445 -1 4 44374 52964 44261 66736 5 83296 61606 81500 34067 6 71170 75045 84275 24960 7 10916 84565 74352 -1 8 27530 34757 4336 13707 9 11525 1059 44409 -1 10 60678 41209 14 16745 11 5425 40846 18885 1528 12 24347 47677 91074 10415 13 86985 67570 67571 14187 14 25284 24778 12238 33329 15 23492 48 1862 25641 16 39989 34371 12933 61807 17 75242 55600 30472 16326 18 60464 15152 48118 22577 19 14537 251 509 44701 20 86743 63502 86747 77841 21 7823 39759 75062 3138 22 53940 35179 85423 5151 23 38343 1369 38333 44439 24 83 28074 43426 8743
La première ligne importe peu, on ne veut pas la modifier, la première colonne non plus car çà décompte le nombre de lignes. Je voudrais modifier les 4 dernières colonnes.
Pour le fichierB, il contient beaucoup moins de lignes, à peu près 500, il est de cette forme :
45 70 5892 42 7915 -10
83 157 98 159 5889 -10
276 77 151 152 5890 -10
353 120 48 47 5890 -10
479 119 14 118 6205 -10
520 85 5891 160 8321 -10
735 157 83 82 5893 -10
767 85 86 145 8321 -10
794 71 70 131 7915 -10
908 113 114 32 7918 -10
910 68 7551 5893 7915 -10
953 100 10 84 5891 -10
1276 76 54 7 5941 -10
1301 5143 5894 5887 5940 -10
1302 150 7806 89 7917 -10
1346 56 5940 5887 8322 -10
1382 5892 5893 5143 7915 -10
1460 133 5887 135 8322 -10
1514 112 114 113 7918 -10
1517 96 99 156 5889 -10
1528 46 13 119 5888 -10
1529 156 98 155 5889 -10
1534 145 66 85 5891 -10
1536 129 128 127 7916 -10
1539 135 5887 74 5941 -10
1546 153 93 96 5889 -10
1565 94 95 154 5890 -10
1646 18 108 22 8332 -10
1876 104 5888 20 6136 -10
Ici seule la première colonne est importante, les 5 dernières colonnes ne servent pas du tout pour la comparaison, elles sont à ignorer.
Par conséquent, le problème est : le fichierA est à modifier comme suit : tous les entiers de la première colonne de fichierB qui apparaissent dans les 4 dernières colonnes de fichierA doivent être remplacé par -1.
Merci encore pour votre aide.
Hors ligne
#5 Le 30/07/2012, à 11:57
- pingouinux
Re : script lecture et écriture fichier
Bonjour,
Ceci devrait faire l'affaire :
#!/bin/bash
# Sauvegarde du fichier A
cp A A.old
# On récupère la 1ère colonne du fichier B + Mise en forme pour utilisation directe dans sed
col1_B=$(awk 'BEGIN{ORS="|"}{print "\\b"$1"\\b"}' B|head -c -1)
# 1ère ligne du fichier A
lig1_A=$(head -n 1 A)
# Partie à vérifier du fichier A (tout sauf la 1ère ligne et la 1ère colonne des suivantes)
a_verifier_A=$(tail -n +2 A|awk '{for(i=2;i<=NF;++i)printf("%s ",$i);print ""}' )
( echo "$lig1_A"; nl -b a <(sed -r "s/$col1_B/-1/g" <<<"$a_verifier_A") ) >A
Édité : Simplification + Commentaires
Dernière modification par pingouinux (Le 30/07/2012, à 12:28)
Hors ligne
#6 Le 30/07/2012, à 13:44
- natacha123
Re : script lecture et écriture fichier
Merci beaucoup !!! Çà répond exactement à ma question
Hors ligne
#7 Le 30/07/2012, à 14:02
- credenhill
Re : script lecture et écriture fichier
hello
awk -v OFS='\t' 'FNR==NR {b[$1]++; next} {for(n=2; n<6; n++)if(b[$n])$n=-1; $1=$1; print}' fichierB fichierA
Hors ligne
#8 Le 30/07/2012, à 15:31
- pingouinux
Re : script lecture et écriture fichier
@credenhill #7 : Belle concision, bravo ! Il faudrait juste ne pas traiter la 1ère ligne du fichier A.
Hors ligne
#9 Le 30/07/2012, à 16:07
- credenhill
Re : script lecture et écriture fichier
effectivement
awk -v OFS='\t' 'FNR==NR {b[$1]++; next} l++ {for(n=2; n<6; n++)if(b[$n])$n=-1; $1=$1} {print}' fichierB fichierA
Hors ligne
#10 Le 31/07/2012, à 03:39
- nesthib
Re : script lecture et écriture fichier
@natacha123 : c'est effectivement plus clair comme ça
@credenhill : bien joué ♥ awk
une petite variante :
awk 'FNR==NR {s=s"|"$1; next} _++ {gsub(substr(s,2),"-1",$0);print}' fichierB fichierA
GUL Bordeaux : Giroll – Services libres : TdCT.org
Hide in your shell, scripts & astuces : applications dans un tunnel – smart wget – trouver des pdf – install. auto de paquets – sauvegarde auto – ♥ awk
⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn
Hors ligne
#11 Le 31/07/2012, à 06:42
- pingouinux
Re : script lecture et écriture fichier
Bonjour,
@nesthib #10 :
Pas mal, en adaptant un tout petit peu la commande qui
Supprime la 1ère ligne du fichier A
Traite aussi la 1ère colonne du fichier A
Remplace les portions de nombres (avec l'exemple donné en #4, 21445 est remplacé par 214-1)
Hors ligne
#12 Le 31/07/2012, à 07:25
- nesthib
Re : script lecture et écriture fichier
effectivement, j'ai écrit ça sans vérifier (honte à moi) :
pour la première ligne, il suffit de sortir le print du groupe conditionné par _++
pour la première colonne, pas compliqué mais du coup ça rajoute 2/3 commandes
pour la détection des mots entier, c'est un problème plus embêtant mais corrigé facilement en utilisant l'opérateur mot entier \<mot\>
awk 'FNR==NR {s=s"|\\<"$1"\\>"; next} _++ {a=$1;$1="";gsub(substr(s,2),"-1",$0)} {print a $0}' fichierB fichierA
bon du coup c'est aussi long que la solution de credenhill
GUL Bordeaux : Giroll – Services libres : TdCT.org
Hide in your shell, scripts & astuces : applications dans un tunnel – smart wget – trouver des pdf – install. auto de paquets – sauvegarde auto – ♥ awk
⃛ɹǝsn xnuᴉꞁ uʍop-ǝpᴉsdn
Hors ligne
#13 Le 31/07/2012, à 10:13
- credenhill
Re : script lecture et écriture fichier
si l'alignement propre en ordre des colonnes n'est pas important on peut faire plus cort
$ awk 'FNR==NR {b[$1]++; next} l++ {for(n=2; n<6; n++)if(b[$n])$n=-1} 1' fichierB fichierA
Hors ligne