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
,
(?= [^"]* " )