IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Lecture colonne par colonne


Sujet :

Shell et commandes GNU

  1. #1
    Nouveau membre du Club
    Femme Profil pro
    etudiant
    Inscrit en
    Avril 2018
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 28
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : etudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 56
    Points : 32
    Points
    32
    Par défaut Lecture colonne par colonne
    Bonjour, je souhaiterai lire mon fichier ligne par ligne et pour chaque ligne lire colonne par colonne pour effectuer des modifications sur chaque colonne. Toutes les colonnes sont séparées par une tabulation.

    Comment faire pour lire une ligne d'un fichier colonne par colonne ?

    Merci

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    awk !

    ou lire une fichier
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 459
    Points
    13 459
    Par défaut
    Bonjour

    Toutes les colonnes sont séparées par une tabulation.
    Comment faire pour lire une ligne d'un fichier colonne par colonne ?
    Avec awk, $i désigne le contenu de la colonne i. Par exemple, $1 est le premier champ de la ligne. Mieux ! $(i+1) est le champ de la colonne d'après. NF est le nombre de colonnes. Donc $NF est le contenu du dernier champ de la ligne.

    Bref, awk est un bon outil pour gérer un fichier organisé en colonnes.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  4. #4
    Nouveau membre du Club
    Femme Profil pro
    etudiant
    Inscrit en
    Avril 2018
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 28
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : etudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 56
    Points : 32
    Points
    32
    Par défaut
    Malgré vos propositions et lien, je ne parviens toujours pas à voir comment faire.

    Mon but est de remplacer chaque colonne de chaque ligne de mon fichier new-vcf.vcf.

    voici une partie de mon fichier new-vcf.vcf :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1	783071	rs142849724	C	T	.	PASS	ENSG00000228794;ENST00000624927|ENST00000623808|ENST00000445118|ENST00000448975|ENST00000610067|ENST00000608189|ENST00000609139|ENST00000449005|ENST00000416570|ENST00000623070|ENST00000609009|ENST00000622921	GT	0|0	0|0	1|0	0|0	1|0	0|0	0|0	0|0	0|0	0|1	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|0	0|1	0|0	0|0	0|0	0|1	0|0	0|0	0|0
    Voici ce que je voudrai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1	783071	rs142849724	C	T	.	PASS	ENSG00000228794;ENST00000624927|ENST00000623808|ENST00000445118|ENST00000448975|ENST00000610067|ENST00000608189|ENST00000609139|ENST00000449005|ENST00000416570|ENST00000623070|ENST00000609009|ENST00000622921	GT	C|C	C|C	T|C	C|C	T|C	C|C	C|C	C|C	C|C	C|T	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|C	C|T	C|C	C|C	C|C	C|T	C|C	C|C	C|C
    grâce à de nombreuses recherches et grâce à vos propositions, je propose le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    #!/bin/bash
     
    while read line
    do
         while IFS='\t' read -r colonne1 colonne2 colonne3 REF ALT colonne6 colonne7 colonne8 colonne9 colonne10 colonne11 colonne12 colonne13 colonne14 colonne15 colonne16 colonne17 colonne18 colonne19 colonne20 colonne21 colonne22 colonne23 colonne24 colonne25 colonne26 colonne27 colonne28 colonne29 colonne30 colonne31 colonne32 colonne33 colonne34 colonne35 colonne36 colonne37 colonne38 colonne39 colonne40 colonne41 colonne42 colonne43 colonne44 colonne45 colonne46 colonne47 colonne48 colonne49; 
    	do 
    		if [[ $colonne9 == "0/0" ]]; then
    			awk '{gsub (/"0/0"/, $REF/$REF, $colonne9}' $line
    		elif [[ $colonne9 == "1/1" ]]; then
    			awk '{gsub (/"1/1"/, $ALT/$ALT, $colonne9}' $line
    		elif [[ $colonne9 == "1/0"  ]]; then
    			awk '{gsub (/"1/0"/, $ALT/$REF, $colonne9}' $line
    		elif [[ $colonne9 == "0/1"  ]]; then
    			awk '{gsub (/"0/1"/, $REF/$ALT, $colonne9}' $line
       		fi
     
       		if [[ $colonne10 == "0/0" ]]; then
    			awk '{gsub (/"0/0"/, $REF/$REF, $colonne10}' $line
    		elif [[ $colonne10 == "1/1" ]]; then
    			awk '{gsub (/"1/1"/, $ALT/$ALT, $colonne10}' $line
    		elif [[ $colonne10 == "1/0"  ]]; then
    			awk '{gsub (/"1/0"/, $ALT/$REF, $colonne10}' $line
    		elif [[ $colonne10 == "0/1"  ]]; then
    			awk '{gsub (/"0/1"/, $REF/$ALT, $colonne10}' $line
       		fi
    	done < $line
    done < new-vcf.vcf
    Cependant, je ne sais pas si c'est la meilleure façon de lire par colonne chaque ligne car comme vous pouvez le voir, le fichier est composé de 49 colonnes.
    Dois-je faire le bloc if pour chaque colonne que je souhaite modifier ?
    Au départ je pensai utiliser une boucle for mais je ne vois pas comment.

    Donc au final, je bloque toujours.

    Merci

  5. #5
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 552
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 552
    Points : 19 392
    Points
    19 392
    Par défaut
    ah, ben, non, ça c'est dégueux : c'est ou le shell, ou awk, mais pas les deux.
    sinon, c'est dégueux contre-optimal puisque pour chaque ligne tu appelles un programme externe.
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    while IFS=$'\t' read -r -a array
    do
       for n in 8 9
       do
          case "${array[$n]}" in
             "0/0") array[$n]="ce que tu veux"
             ;;
             etc) etc...
             ;;
          esac
       done
       printf '%s\t' "${array[@]::${#array[@]}-1}"; echo "${array[@]: -1}"
    done <fichier.in >fichier.out
    par contre, si le fichier comporte beaucoup de lignes (plus que quelques centaines), il vaut mieux utiliser awk qui est beaucoup plus rapide.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  6. #6
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 459
    Points
    13 459
    Par défaut
    Bon. Ce n'est pas totalement clair. Voilà ce que je comprends :
    Tu veux qu'à partir du champ 10, et jusqu'à la fin de la ligne, les 0 soient remplacés par le champ 3 et les 1 par le champ 4.
    N'est ce pas ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ cat parcolonne.txt
    1       783071  rs142849724     C       T       .       PASS    ENSG00000228794;ENST00000624927|ENST00000623808|ENST00000445118|ENST00000448975|ENST00000610067|ENST00000608189|ENST00000609139|ENST00000449005|ENST00000416570|ENST00000623070|ENST00000609009|ENST00000622921 GT0|0     0|0     1|0     0|0     1|0     0|0     0|0     0|0     0|0     0|1     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|1     0|0     0|0       0|0     0|1     0|0     0|0     0|0
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ awk -F '\t' -vOFS='\t' '{for (c=10;c<=NF;c++) {gsub(/0/,$4,$c);gsub(/1/,$5,$c);} } 1' parcolonne.txt
    1       783071  rs142849724     C       T       .       PASS    ENSG00000228794;ENST00000624927|ENST00000623808|ENST00000445118|ENST00000448975|ENST00000610067|ENST00000608189|ENST00000609139|ENST00000449005|ENST00000416570|ENST00000623070|ENST00000609009|ENST00000622921 GTC|C     C|C     T|C     C|C     T|C     C|C     C|C     C|C     C|C     C|T     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|T     C|C     C|C       C|C     C|T     C|C     C|C     C|C
    Quelques non-évidences:
    • Il faut définir le séparateur de sortie comme le séparateur d'entrée, sinon il remplace les tabulations par des espaces. (FS=Field Separator; OFS=Output Field Separator)
    • gsub() fait comme sub() une substitution mais pour toutes les correspondances (non chevauchantes). Ici, plusieurs 0 dans le champ seront remplacés.
    • $c désigne le contenu de la colonne de rang égal à l'indice de boucle for.
    • "1" en fin de script imprime toutes les lignes. "1" est toujours vrai donc fait toujours l'action. Et comme l'action n'est pas définie, c'est l'action par défaut: l'impression sur la sortie.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  7. #7
    Nouveau membre du Club
    Femme Profil pro
    etudiant
    Inscrit en
    Avril 2018
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 28
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : etudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 56
    Points : 32
    Points
    32
    Par défaut
    Citation Envoyé par N_BaH Voir le message
    ah, ben, non, ça c'est dégueux : c'est ou le shell, ou awk, mais pas les deux.
    sinon, c'est dégueux contre-optimal puisque pour chaque ligne tu appelles un programme externe.
    Code bash : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    while IFS=$'\t' read -r -a array
    do
       for n in 8 9
       do
          case "${array[$n]}" in
             "0/0") array[$n]="ce que tu veux"
             ;;
             etc) etc...
             ;;
          esac
       done
       printf '%s\t' "${array[@]::${#array[@]}-1}"; echo "${array[@]: -1}"
    done <fichier.in >fichier.out
    par contre, si le fichier comporte beaucoup de lignes (plus que quelques centaines), il vaut mieux utiliser awk qui est beaucoup plus rapide.
    Merci de votre aide. En effet, mon fichier contient 17 millions de lignes donc ça fait beaucoup :/ et je connais awk mais pour les commande de "base" mais je souhaite mon perfectionner dans ce langage qui très puissant. Je recherche donc des cours en ligne ou livre ... pour approfondir mes connaissances sur ce langage

  8. #8
    Nouveau membre du Club
    Femme Profil pro
    etudiant
    Inscrit en
    Avril 2018
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 28
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : etudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 56
    Points : 32
    Points
    32
    Par défaut
    Citation Envoyé par Flodelarab Voir le message
    Bon. Ce n'est pas totalement clair. Voilà ce que je comprends :
    Tu veux qu'à partir du champ 10, et jusqu'à la fin de la ligne, les 0 soient remplacés par le champ 3 et les 1 par le champ 4.
    N'est ce pas ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ cat parcolonne.txt
    1       783071  rs142849724     C       T       .       PASS    ENSG00000228794;ENST00000624927|ENST00000623808|ENST00000445118|ENST00000448975|ENST00000610067|ENST00000608189|ENST00000609139|ENST00000449005|ENST00000416570|ENST00000623070|ENST00000609009|ENST00000622921 GT0|0     0|0     1|0     0|0     1|0     0|0     0|0     0|0     0|0     0|1     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|1     0|0     0|0       0|0     0|1     0|0     0|0     0|0
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ awk -F '\t' -vOFS='\t' '{for (c=10;c<=NF;c++) {gsub(/0/,$4,$c);gsub(/1/,$5,$c);} } 1' parcolonne.txt
    1       783071  rs142849724     C       T       .       PASS    ENSG00000228794;ENST00000624927|ENST00000623808|ENST00000445118|ENST00000448975|ENST00000610067|ENST00000608189|ENST00000609139|ENST00000449005|ENST00000416570|ENST00000623070|ENST00000609009|ENST00000622921 GTC|C     C|C     T|C     C|C     T|C     C|C     C|C     C|C     C|C     C|T     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|C     C|T     C|C     C|C       C|C     C|T     C|C     C|C     C|C
    Quelques non-évidences:
    • Il faut définir le séparateur de sortie comme le séparateur d'entrée, sinon il remplace les tabulations par des espaces. (FS=Field Separator; OFS=Output Field Separator)
    • gsub() fait comme sub() une substitution mais pour toutes les correspondances (non chevauchantes). Ici, plusieurs 0 dans le champ seront remplacés.
    • $c désigne le contenu de la colonne de rang égal à l'indice de boucle for.
    • "1" en fin de script imprime toutes les lignes. "1" est toujours vrai donc fait toujours l'action. Et comme l'action n'est pas définie, c'est l'action par défaut: l'impression sur la sortie.
    Je vous remercie, cela convient parfaitement, Merci. Je vais décrypter votre code pour bien comprendre les étapes réalisées. Encore Merci

    Petite question :
    Pourquoi commencer le "compteur" c à 10 ?

    De plus, est-il possible de faire :
    est-il possible de transformer au préalable, les 0|0 en 0 et les 1|1 en 1 ?

  9. #9
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 459
    Points
    13 459
    Par défaut
    Pourquoi commencer le "compteur" c à 10 ?
    Car on commence à remplacer à partir de la 10ème colonne.
    Veux-tu vraiment "ENSTCCCCC445TT8" au lieu de "ENST00000445118" ?

    est-il possible de transformer au préalable, les 0|0 en 0 et les 1|1 en 1 ?
    En sed, j'aurai naturellement fait ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed 's@\([01]\)|\1@\1@g'
    Ce qui marche bien.
    Mais gawk a l'air d'avoir du mal avec les références arrières dans la regex recherchée. Il en veut bien dans la sortie, mais pas dans l'entrée.

    Donc on fait à la main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    $ awk -F '\t' -vOFS='\t' '{for (c=10;c<=NF;c++) {sub(/0\|0/,"0",$c);sub(/1\|1/,"1",$c);gsub(/0/,$4,$c);gsub(/1/,$5,$c);} } 1' parcolonne.txt
    1       783071  rs142849724     C       T       .       PASS    ENSG00000228794;ENST00000624927|ENST00000623808|ENST00000445118|ENST00000448975|ENST00000610067|ENST00000608189|ENST00000609139|ENST00000449005|ENST00000416570|ENST00000623070|ENST00000609009|ENST00000622921 GTC       C       T|C     C       T|C     C       C       T       C       C|T     C       C       C       C       C       C       C       C       C       C       C       C       C       C       C       C       C       C       C       C       C       C       C|T     C       C       C       C|T     C       C       C
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

  10. #10
    Nouveau membre du Club
    Femme Profil pro
    etudiant
    Inscrit en
    Avril 2018
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 28
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : etudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Avril 2018
    Messages : 56
    Points : 32
    Points
    32
    Par défaut
    En effet, je suis bête, je n'avais pas réfléchie à ça, désoler.

    Je vous remercie et vous suis très reconnaissante pour votre aide précieuse ! Elle m'a été d'une très grande aide et c'est pourquoi je vous remercie milles fois ! un très grand Merci. Je vais tenter de m'améliorer en Awk que je ne connais que très peu grâce à l'ouvrage de Arnold Robbins, Effective AWK Programming, 4e .

  11. #11
    Expert éminent sénior Avatar de Flodelarab
    Homme Profil pro
    Inscrit en
    Septembre 2005
    Messages
    5 243
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente (Poitou Charente)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 5 243
    Points : 13 459
    Points
    13 459
    Par défaut
    Sur internet, GNU awk manual (clic) est une bonne référence. Les principes, les fonctions, intégrées ou non, etc sont bien expliquées.
    On ne lit pas tout d'un coup. Mais il y a des choses à glaner.
    Cette réponse vous apporte quelque chose ? Cliquez sur en bas à droite du message.

Discussions similaires

  1. lecture colonne excel donne nullPointer
    Par Diablo143 dans le forum Débuter avec Java
    Réponses: 8
    Dernier message: 14/06/2017, 09h04
  2. Problème lecture colonne dans un fichier .prn
    Par nilsmatlab dans le forum MATLAB
    Réponses: 2
    Dernier message: 07/07/2011, 16h57
  3. Lecture colonne date avec Spreadsheet.ParseExcel
    Par best94 dans le forum Modules
    Réponses: 3
    Dernier message: 25/11/2008, 16h04
  4. proc append : lecture colonne
    Par stefsas dans le forum SAS Base
    Réponses: 1
    Dernier message: 16/07/2008, 14h09
  5. [langage] Lecture caractère par caractère
    Par And_the_problem_is dans le forum Langage
    Réponses: 3
    Dernier message: 03/12/2002, 16h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo