Forum Programmation.autre parser un fichier texte

Posté par  .
Étiquettes : aucune
0
18
fév.
2008
Bonjour,

Je voudrais parser un fichier txt. Mon fichier provient d'une base de donnée et est comme suit :

sit1, gene1, cancer
sit1, gene2, cancer
..
sit1, genen, cancer
sit2, gene1, cancer
sit2, gene2, cancer
...
sit2, genem, cancer

et je voudrais obtenir un nouveau fichier avec ce schéma là :


sit1, gene1, gene2, ..., genen, cancer
sit2, gene1, gene2, ..., genem, cancer
...
sitp, gene1, gene2, ..., geneq, cancer


On regroupe donc sur une même ligne tous les gènes intervenant dans la situation (sit).

Voila il parait que un langage dénommé awk peut faire cela mais n'y connaissant rien, je vous demande de l'aide :p

Merci d'avance
  • # Alors...

    Posté par  . Évalué à 2.

    Je ne sai spas si j'ai bien pigé. Vérifie mais j'ai peut être un bout de Perl qui pourrait te faire l'affaire.

    Fichier source:

    omnikron@calimero:~$ cat source
    sit1, gene1, cancerX
    sit1, gene2, cancerY
    sit1, gene3, cancerY
    sit1, gene4, cancerY
    sit1, gene5, cancerY
    sit2, gene1, cancerX
    sit2, gene2, cancerZ
    sit2, gene3, cancerZ
    sit3, gene1, cancerY


    Script en Perl:

    #!/usr/bin/perl

    my @source = `cat $ARGV[0]`;
    my %out;

    foreach $s (@source) {
        chomp($s);

        if($s =~ /^(.+),\s+(.+),\s+(.+)$/) {

            push(@{$out{$3}{$1}}, $2);
        }
    }

    while (($cancer, $hsite) = each(%out)) {


        while (($site, $gens) = each(%$hsite)) {
            print($site.",".join(",", @$gens).",".$cancer."\n");
        }
    }


    Appel du script + sort + résultat:

    omnikron@calimero:~$ ./parse.pl source |sort
    sit1,gene1,cancerX
    sit1,gene2,gene3,gene4,gene5,cancerY
    sit2,gene1,cancerX
    sit2,gene2,gene3,cancerZ
    sit3,gene1,cancerY
    • [^] # Re: Alors...

      Posté par  . Évalué à 1.

      Tout d'abord merci de répondre.

      J'ai essayé ton code mais il ne se passe rien quand je lance le script.
      Rien ne s'affiche
  • # awk

    Posté par  . Évalué à 3.

    Awk permet en effet de traiter ce probleme.
    L'enoncé est par contre un peu vague. Par exemple, je ne sais pas si le troisieme champs est toujours "cancer", ou si il peut etre vide, ou si il decrit different cancer, comme cela a été suggéré plus haut.

    Dans le cas ou l'on cherche à identifier les lignes comportant le mot cancer, et seulement celles ci, puis à regrouper les genes pour chaque situation, le code suivant devrait faire l'affaire :

    awk -F, '/cancer/{gene[$1] = gene[$1] "," $2} END{ OFS=","; for (val in gene) print val, gene[val], "cancer"}' cancer.txt

    que l'on peut lancer d'une seule ligne à l'invite de commande.

    Si il y a plusieurs types de cancer, on peut egalement modifier le code , il suffit de demander !

    • [^] # Re: awk

      Posté par  . Évalué à 1.

      ben en faite mais donner son de type numérique, j'ai donc cela

      1, 14 , 1
      1, 123, 1
      1, 3732, 1
      2, 432, 0
      2, 232, 0
      2, 84, 0

      et je voudrais obtenir cela :
      1, 14, 123, 3732, 1
      2, 432, 232, 84, 0

      Pour une situation donné (premier nombre) il y a soit cancer 1, soit pas cancer 0 (dernier chiffre).
      Le deuxieme nombre represente l'identifiant du gene en faite.

      Voila je pense que maintenant cela doit être plus claire.

      Et merci des réponses
      • [^] # Re: awk

        Posté par  . Évalué à 1.

        Le code Perl sort ci-dessus fonctionne toujours et sort
        omnikron@calimero:~$ ./plop.pl cancer.txt
        1,14 ,123,3732,1
        2,432,232,84,0


        Tu peux changer la ligne...
        if($s =~ /^(.+),\s+(.+),\s+(.+)$/) {


        ... par ...
        if($s =~ /^\s+(.+)\s+,\s+(.+)\s+,\s+(.+)\s+$/) {


        Histoire de pas être embêté par les espaces.
      • [^] # Re: awk

        Posté par  . Évalué à 2.

        Ok, je comprends.

        Dans ce cas :

        awk -F, '{cancer[$1] = $3; gene[$1] = gene[$1] " " $2} END{ OFS=","; for (val in gene) print val, gene[val], cancer[val]}' cancer.txt

        Ensuite, tu peux choisir de n'afficher que les situations pour lesquelles il y a un cancer :

        awk -F, '$3 == 1{ gene[$1] = gene[$1] " " $2} END{ OFS=","; for (val in gene) print val, gene[val], 1}' cancer.txt

        ou celles pour lesquelles il n'y en a pas :

        awk -F, '$3 == 0{gene[$1] = gene[$1] " " $2} END{ OFS=","; for (val in gene) print val, gene[val], 0}' cancer.txt
  • # Ruby

    Posté par  . Évalué à 1.

    En supposant qu'il n'y a qu'un seul type de cancer:

    fichier 'source.txt':

    sit1, gene1, cancer
    sit1, gene2, cancer
    sit1, gene3, cancer
    sit1, gene4, cancer
    sit1, gene5, cancer
    sit2, gene1, cancer
    sit2, gene2, cancer
    sit2, gene3, cancer
    sit3, gene1, cancer


    fichier 'parser.rb':

    src = open('source.txt') {|io| io.readlines }

    r = Hash.new {|h,k| h[k]=[] }

    src.inject(r) do |h,l|
    sit, *genes = l.split(', ')[0..-2]
    h[sit] << genes
    h[sit].flatten
    h
    end

    r.map {|k,v| puts "#{k}, #{v.join(', ')}, cancer" }
  • # ...

    Posté par  (site web personnel) . Évalué à 2.

    Il fut un temps ou les gens se faisaient jeter quand ils demandaient à la communauté linuxfr de faire leurs devoirs...
    • [^] # Re: ...

      Posté par  . Évalué à 1.

      Arf, ça nous amuse de tripatouiller un peu :-) C'était marrant de refaire un bout de Perl. J'ai toujours aimé Perl pour ce genre de trucs et quand on relis on se rend compte à quel point c'est parfois une syntaxe imbitable. Par contre c'est sûr que la solution AWK en une commande est élégante... mais tout aussi imbitable pou moi :D

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.