J'ai un fichier de données délimité avec une entrée utilisateur que je dois nettoyer. Plus précisément:
"INC \ d {12}"
(les guillemets font partie du modèle). li>
\ n
doit être remplacé par un seul espace s'il n'est pas immédiatement suivi du motif "INC\d{12}"
Voici quelques données d'entrée simulées (j'ai sauvegardé mon dans un fichier nommé test_input_so.txt
):
perl -pe 's/\n(?!"INC\d{12})/ /g;' test_input_so.txt
Voici la sortie souhaitée pour les données ci-dessus:
"INC000111111111", "field2", "field3" "INC000222222222", "field2", "field3","INC000123456789 blahblah" "INC000444444444", "fie"""ld2", "field3" "INC000123456789", "field2", "field3", "INC000333333333", "INC000123456789", "field3"" "INC000555555555", "field2", "field3","field4"
J'ai essayé plusieurs combinaisons de lookaheads / backs négatifs, mais je ne sais pas pourquoi cela ne fonctionne pas.
Voici un exemple:
"INC000111111111", "field2", "field3" "INC000222222222", "field2", "field3","INC000123456789 blahblah" "INC000444444444", "fie"""ld2", "field3" "INC000123 456789", "field2", "field3", "INC000333333333", "INC000123456789", "field3"" "INC000555555555", "field2", "fiel d3","field4"
Il supprime tout \ n
, mais supprime incorrectement le \ n
suivi de "INC123456789012" qui aurait dû être laissé en place.
3 Réponses :
perl -pe ...
fonctionne avec une ligne à la fois, donc une expression régulière multiligne ne vous fera aucun bien.
Le -0
passer en Perl peut changer votre séparateur d'enregistrement d'entrée (ce que Perl notion de ligne est) et vous permet d’opérer sur l’entrée entière sous la forme d’une seule chaîne.
perl -0777 -pe 's/\n(?!"INC\d{12})/ /g;' test_input_so.txt
il supprime INC000123456789
de la sortie attendue, mais il contredit également l'exigence d'OP "INC \ d {12}"
pourriez-vous s'il vous plaît revoir ma réponse et suggérer des améliorations.
Tout d'abord, vous avez des guillemets errants que vous devez corriger pour que vos données puissent être valides au format CSV:
"fie" "" ld2 "
doit être "fie""ld2"
Deuxièmement, ne mettez pas d'espace après la virgule entre les champs: pas a, b
mais a,b
Une fois que vous avez réparé ces éléments, vous pouvez utiliser le module Text :: CSV : p >
Ce que je pense que vous voulez vraiment faire, c'est supprimer les nouvelles lignes qui sont à l'intérieur des champs entre guillemets . La structure de ce code est tirée du perldoc Text :: CSV.
"INC000111111111","field2","field3" "INC000222222222","field2","field3","INC000123456789 blahblah" "INC000444444444","fie""ld2","field3" "INC000123456789","field2","field3","" "INC000333333333","INC000123456789","field3" "INC000555555555","field2","field3","field4"
perl -MData::Dump=dd -E ' use Text::CSV; my $csv = Text::CSV->new ({ binary => 1, always_quote => 1 }) or die "Cannot use CSV: ".Text::CSV->error_diag (); my $file = shift @ARGV; open my $fh, "<:encoding(utf8)", $file or die; while ( my $row = $csv->getline( $fh ) ) { my @row = map {s/\n//g; $_} @$row; $csv->combine(@row); my $line = $csv->string(); say $line if $line ne q{""}; } $csv->eof or $csv->error_diag(); close $fh; ' test_input_so.txt
Un autre Perl
$ cat test_input_so.txt "INC000111111111", "field2", "field3" "INC000222222222", "field2", "field3","INC000123456789 blahblah" "INC000444444444", "fie"""ld2", "field3" "INC000123 456789", "field2", "field3", "INC000333333333", "INC000123456789", "field3"" "INC000555555555", "field2", "fiel d3","field4" $
Entrée:
$ perl -0777 -ne ' while( /(^"INC00.+?)(\n"INC.*|\Z)/msg ) { $x=$1;$_=$2; $x=~s/\n//g; print "$x\n" } ' test_input_so.txt "INC000111111111", "field2", "field3" "INC000222222222", "field2", "field3","INC000123456789 blahblah" "INC000444444444", "fie"""ld2", "field3" "INC000123456789", "field2", "field3", "INC000333333333", "INC000123456789", "field3"" "INC000555555555", "field2", "field3","field4" $