Comment copier des chaînes de caractère différente [Fermé]

Signaler
Messages postés
20
Date d'inscription
vendredi 30 mars 2018
Statut
Membre
Dernière intervention
22 août 2018
-
Messages postés
5550
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 mai 2021
-
Bonjour à tous !

Je découvre le perl et j'aimerai pouvoir copier dans un fichier le nom d'isotopes pour les coller dans un autre fichier. Seul problème, ces noms d'isotopes ont un nombre de caractères qui est de 6 maximum ( ex : SN129M) et lorsque le nom de l'isotope n'est pas composé de 6 caractères, les caractères sont remplacés par des espaces (ex : C 13 pour le carbone 13. Noter qu'il y a un espace avant et après le C et un espace après le 3). J'aimerai donc pouvoir identifier dans mon fichiers les chaines de ce type pour ensuite les copier dans un autre fichier.
Connaissez-vous une fonction permettant de faire ça ?

Merci d'avance pour vos réponses et conseils !

1 réponse

Messages postés
5550
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 mai 2021
934
Salut am33450,

La regexp
([A-Z0-9 ]{6})
permet de matcher un groupe de 6 caractères consécutifs, composés de lettres majuscules, de chiffres ou d'espaces.


Dal
Messages postés
20
Date d'inscription
vendredi 30 mars 2018
Statut
Membre
Dernière intervention
22 août 2018

Salut Dal,

Merci !

Pour l'instant avec mon programme, lorsque je rencontre une chaîne de 6 caractères dans mon fichier 1, je copie toute la ligne dans un fichier 2 (donc des informations inutiles).

Or j'aimerai seulement copier cette chaîne de caractère (le nom des isotopes) et faire ça à chaque fois que mon programme en trouve dans mon fichier 1 :
exemple :

lorsque j'ai une ligne comme ça dans le fichier 1 :
eg CU_72 1.0045782E9
eg CU_73 1.0293612E9

J'aimerai obtenir dans un fichier 2 :

CU 72
CU 73


Sais-tu comment je pourrais faire ? Si tu as un exemple je suis preneur !
Merci d'avance,
Am
Messages postés
5550
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 mai 2021
934
Il y a 5 caractères dans "CU_72" (sauf si on compte l'espace avant ou après) et un underscore qui ne fait pas partie des caractères que tu as mentionnés au début.

Bref, si on ajoute l'underscore aux caractères permis et que l'on reste sur 6 caractères, tu peux utiliser la regexp pour extraire ce qui t'intéresse :

#!/usr/bin/perl

use strict;
use warnings;

my $st = "CU_72 1.0045782E9";

if ($st =~ /([A-Z0-9 _]{6})/) {
    my $match = $1;
    print "matched: [$match]\n";
    # remplacer les underscores
    # par un espace 
    $match =~ s/_/ /g;
    print "converted to: [$match]\n";
} else {
    print "wrong format\n";
}

qui donne à l'exécution :
matched: [CU_72 ]
converted to: [CU 72 ]

La variable $1 permet d'accéder au contenu capturé correspondant aux parenthèses de la regexp (si la regexp était composée de plusieurs expressions entre parenthèses, les autres captures seraient accessibles avec $2, $3, etc.).

Si tes données commencent systématiquement en début de ligne, tu peux affiner la regexp pour qu'elle ne matche qu'en début de ligne :
if ($st =~ /^([A-Z0-9 _]{6})/)


Dal
Messages postés
20
Date d'inscription
vendredi 30 mars 2018
Statut
Membre
Dernière intervention
22 août 2018

Merci,
Oui en effet, il y a 6 caractères dans [ 72 ] car je compte l'espace à la fin.
______________________________________________________________________________________
Mon code est pour l'instant comme ça :

#!/usr/bin/perl
# =============================================================================
# Imports
# =============================================================================
use strict;
use warnings;
use autodie;


open (FICHIER, ">fichier.txt") || die ("Vous ne pouvez pas créer le fichier \"fichier.txt\"");
open(F,"f1") || die ("Erreur d'ouverture du fichier f1") ;
print FICHIER "Darwin \n";
my $mot = "";
while (<F>) {
$_ =~ s/\n//g;
if ($_ =~ / \w\w\w\w\w(\w| )/){
$_ =~ s/(_)+(?=[A-Za-z])//g;
$_ =~ s/(___)+(?=[0-9])/ /g;
$_ =~ s/(__)+(?=[0-9])/ /g;
$_ =~ s/(_)+(?=[0-9])/ /g;
$mot = $_;
print FICHIER $mot;
print FICHIER "\n";
}
}
close (F);
print FICHIER "Cesar \n";
open(F,"f2") || die ("Erreur d'ouverture du fichier f2") ;
while (<F>) {
$_ =~ s/\n//g;
if ($_ =~ / \w(\w| )(\w| )(\w| )\w(\w| )/){
$_ =~ s/(_)+(?=[A-Za-z])//g;
$_ =~ s/(___)+(?=[0-9])/ /g;
$_ =~ s/(__)+(?=[0-9])/ /g;
$_ =~ s/(_)+(?=[0-9])/ /g;
$mot = $_;
my @tab = ();
print FICHIER $_;
print FICHIER "\n";
}
}
close (F);
close (FICHIER);
open (FICHIER, "fichier.txt") || die ("Vous ne pouvez pas créer le fichier \"fichier.txt\"");
open (FIC, ">iso.txt") || die ("Vous ne pouvez pas créer le fichier \"fichier.txt\"");
while (<FICHIER>) {
if ($_ =~ /([A-Z0-9 ]{6})/){
my $match = $1;
print FIC "$match\n";
}
}
close (FICHIER);
close (FIC);
______________________________________________________________________________________


En fait je lis deux fichiers résultats dont le formalisme d'écriture est différent. Donc d'abord je les mets dans le même formalisme (en remplaçant les "_" par des espaces etc) puis j'aimerai copier tout les noms d'isotopes que je rencontre dans ces fichiers résultat dans un troisième fichier.
Or pour l'instant je n'arrives qu'à copier des lignes. Donc au final j'ai testé de créer un quatrième fichier dans lequel (grâce à ce que tu m'as montré précédemment) je récupère les chaines de 6 caractères composés de d'espace, lettres et chiffres.
Jusque là les 2 problèmes qu'il me reste sont :
-les fichiers résultats ne contiennent pas que des noms d'isotopes donc j'ai parfois des mots (de 6 caractères) qui sont copiés
-si j'ai plusieurs noms d'isotope sur une même ligne, seul le premier est copié.


Voici un extrait des fichiers que j'utilise :

Fichier f1 :

LISTE ORDONNEE DES ISOTOPES :
H 3 C 14 TH233 U239 NP236F NP236M AM242M CM243
BK246 BK250 CF251 CF253 TL207M FR224 CF246 CU 71

_H__3 1.0392E+13 0.0000E+00 1.0392E+13
_C_14 2.6451E+08 0.0000E+00 2.6451E+08

Fichier f2 :

--------------------------
| ISOTOPE | INITIALE |
--------------------------
| H 1 | 2.033043e+23 |
| H 2 | 3.050022e+19 |
| B 10 | 4.401455e+21 |
| B 11 | 1.771641e+22 |

Le script me donne pour l'instant :

Fichier "fichier.txt" :

LISTE ORDONNEE DES ISOTOPES :
H 3 C 14 TH233 U239 NP236F NP236M AM242M CM243
BK246 BK250 CF251 CF253 TL207M FR224 CF246 CU 71
H 3 1.0392E+13 0.0000E+00 1.0392E+13
C 14 2.6451E+08 0.0000E+00 2.6451E+08
eG CU_71 3.4182E+11 0.0000E+00 3.4182E+11
| H 1 | 2.033043e+23 |
| H 2 | 3.050022e+19 |
| B 10 | 4.401455e+21 |
| B 11 | 1.771641e+22 |

Fichier "iso.txt" :

LIST
H 3
BK246
H
C
G CU
H 1
H 2
B 10
B 11

Et moi je voudrais arriver à :
H 3
C 14
TH233
U239
NP236F
NP236M
AM242M
CM243
BK246
BK250
CF251
CF253
TL207M
FR224
CF246
CU 71
H 3
C 14
CU
H 1
H 2
B 10
B 11


J'espère que je suis clair ...

Merci d'avance
Messages postés
5550
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 mai 2021
934
Donc pour tes données de départ, tu as :

Fichier f1 :

LISTE ORDONNEE DES ISOTOPES :
H 3 C 14 TH233 U239 NP236F NP236M AM242M CM243
BK246 BK250 CF251 CF253 TL207M FR224 CF246 CU 71

_H__3 1.0392E+13 0.0000E+00 1.0392E+13
_C_14 2.6451E+08 0.0000E+00 2.6451E+08

Fichier f2 :

--------------------------
| ISOTOPE | INITIALE |
--------------------------
| H 1 | 2.033043e+23 |
| H 2 | 3.050022e+19 |
| B 10 | 4.401455e+21 |
| B 11 | 1.771641e+22 |

et ce que tu veux obtenir :
H  3     
C 14
TH233
U239
NP236F
NP236M
AM242M
CM243
BK246
BK250
CF251
CF253
TL207M
FR224
CF246
CU 71
H 3
C 14
CU
H 1
H 2
B 10
B 11

C'est bien ces formats ?

Dans le fichier 1, ce sont des espaces ou des tabulations qui séparent les données ?

Lorsque tu postes du code, ou du texte formaté avec des espaces, utilise la balise "code" du forum pour que cela s'affiche correctement, sinon le HTML écrase les espaces (pour récupérer ce format, j'ai dû afficher le code source de la page web du forum).

pour retirer les dupliqués, le mieux est de mettre les données capturées dans un tableau Perl pour les traiter - il y cependant différentes possibilités - la préservation de l'ordre d'apparition est-il important ?

Dal
Messages postés
5550
Date d'inscription
mercredi 15 septembre 2004
Statut
Contributeur
Dernière intervention
12 mai 2021
934
pff, la balise code a aussi écrasé certains espaces :-(

tel que je vois le contenu de f1, après la ligne "LISTE ORDONNEE DES ISOTOPES :", les items à capturer sont séparés par 3 caractères espace, y compris le dernier de chaque ligne.

Si tel est le cas, le code suivant capture le contenu des fichiers f1 et f2, met les items en tant que clefs d'un hash pour s'assurer qu'ils sont uniques, et affiche les clefs en ordre alphabétique

#!/usr/bin/perl

use strict;
use warnings;

my %hash;
my $info;

# process f1 file
my $file = 'f1';
open $info, $file or die "Could not open $file: $!";
while (my $line = <$info>) {
    # we are interested only in lines after the 1st
    if ($. > 1) {
        # we process lines until we find an empty line
        # or containing only blank characters
        if ($line =~ /^\s+$/) {
            last;
        }
        print "processing: $line";
        for my $item ($line =~ /([A-Z0-9 ]{6})\s{3}/g) {
            $hash{$item} = "1";
        }
    }
}
close $info;

# process f2 file
$file = 'f2';
open $info, $file or die "Could not open $file: $!";
while (my $line = <$info>) {
    # we are interested only in lines after the 3rd
    if ($. > 3) {
        print "processing: $line";
        if ($line =~ /\|\s([A-Z0-9 ]{6}).*/) {
            $hash{$1} = "1";
        }
    }
}

print "hash contains the following keys in alphabetical order:\n";
foreach my $key (sort keys %hash) {
    print "$key\n";
}

donne :
$ ./extract.pl 
processing: H 3 C 14 TH233 U239 NP236F NP236M AM242M CM243
processing: BK246 BK250 CF251 CF253 TL207M FR224 CF246 CU 71
processing: | H 1 | 2.033043e+23 |
processing: | H 2 | 3.050022e+19 |
processing: | B 10 | 4.401455e+21 |
processing: | B 11 | 1.771641e+22 |
hash contains the following keys in alphabetical order:
C 14
H 3
U239
AM242M
B 10
B 11
BK246
BK250
CF246
CF251
CF253
CM243
CU 71
FR224
H 1
H 2
NP236F
NP236M
TH233
TL207M
$

Si tu as des questions sur le code, n'hésites pas à les poser.

Dal