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 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 : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde 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 smile

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 smile
@credenhill : bien joué smile ♥ awk

une petite variante :

awk 'FNR==NR {s=s"|"$1; next} _++ {gsub(substr(s,2),"-1",$0);print}' fichierB fichierA

GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde 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 tongue


GUL Bordeaux : GirollServices libres : TdCT.org
Hide in your shell, scripts & astuces :  applications dans un tunnelsmart wgettrouver des pdfinstall. auto de paquetssauvegarde 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