J'ai une chaîne qui provient d'un fichier CSV:
'NA19900,4,111629038,0;0,0;0,"GSA-rs16997168;rs16997168;rs2w34r23424",C,T,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0';
qui devrait être traduit (en quelque sorte) en
my $str = 'NA19900,4,111629038,0;0,0;0,"GSA-rs16997168,rs16997168,rs2w34r23424",C,T,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0';
pour que Le split
de perl ne divise pas le champ unique GSA-rs16997168, rs16997168
en deux champs séparés
ie la virgule doit être remplacée par un point-virgule si elle est entre les deux "
Je ne trouve pas comment faire cela sur Google
Ce que j'ai essayé jusqu'à présent:
$ str = ~ s / "([^"] +), ([^ "] +)" / "$ 1; $ 2" / g;
mais cela échoue avec> 2 expressions
Ce serait génial si je pouvais en quelque sorte dire à la fonction split
de Perl de compter tout ce qui se trouve dans ""
comme un seul champ même si ce texte a le ,
délimiteur, mais je ne sais pas comment faire ça :(
J'ai entendu parler des lookaheads, mais je ne vois pas comment je peux les utiliser ici :(
3 Réponses :
Je suppose que nous souhaitons capturer jusqu'à quatre virgules après le dernier "
, pour lequel nous commencerions par une expression simple telle que:
use strict; my $str = 'NA19900,4,111629038,0;0,0;0,"GSA-rs16997168,rs16997168,rs2w34r23424",C,T,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0'; my $regex = qr/(.*",.+?,.+?,.+?,.+?),/mp; if ( $str =~ /$regex/g ) { print "Whole match is ${^MATCH} and its start/end positions can be obtained via \$-[0] and \$+[0]\n"; # print "Capture Group 1 is $1 and its start/end positions can be obtained via \$-[1] and \$+[1]\n"; # print "Capture Group 2 is $2 ... and so on\n"; } # ${^POSTMATCH} and ${^PREMATCH} are also available with the use of '/p' # Named capture groups can be called via $+{name}
(.*",.+?,.+?,.+?,.+?),
Pourquoi essayer de recréer un analyseur CSV alors qu'il en existe de parfaits bons?
use Text::CSV_XS qw( ); my $csv = Text::CSV_XS->new({ binary => 1, auto_diag => 2 }); while ( my $row = $csv->get_line($fh) ) { $row->[5] =~ s/,/;/g $csv->say(\*STDOUT, $row); }
Pourquoi utiliser un module CSV et une expression régulière.
Utilisez simplement une expression régulière et supprimez le intermédiaire.
$ str = ~ s / (? m: (?:, | ^) "| (?! ^) \ G) [^",] * \ K, (? = [^ "] * ") /; / g;
https: // regex101. com / r / tRDCen / 1
Version Lisez-moi
(?m: (?: , | ^ ) " | (?! ^ ) \G ) [^",]* \K , (?= [^"]* " )