2012-03-17 9 views
0

Je voudrais trouver et remplacer les dates dans un fichier CSV dans les conditions suivantes:Perl RegEx - Rechercher et remplacer chaîne répétée

1) La première à colonnes sont vides, comme « », « »,

1a) $ cas [1] ne doit pas correspondre à cause du texte dans les deux premières colonnes

2) Chacune des 6 colonnes suivantes peuvent contenir des dates, comme dans le cas de $ [0] ci-dessous

2a $ case [2] ne doit pas correspondre puisque les 6 colonnes sont vides

my @case = (
'"","","","1/2/2012","","","","",="12345678"', 
'"Add","New","1/1/2012","1/2/2012","","","",""="0987654"', 
'"","","","","","","","",="91234567"' 
); 

J'ai utilisé le code suivant, mais il correspond à tort $ cas [2] et les effets d'efficacité de script:

my $argFind = (qr/^"","",("[\d\/]*",){6}(.*)/); 

$replace = '"","","","","","","","",'; 

if (grep(/$argFind/,@case)) 
{ 
     s/$argFind/$replace$2/ for @case; 
     #write file 
    } 

Le résultat final devrait être comme:

$case = [ 
'"","","","","","","","",="12345678"', 
'"Add","New","1/1/2012","1/2/2012","","","",""="0987654"', 
'"","","","","","","","",="91234567"' 
]; 
+0

Exigence 2: L'une des 6 colonnes peut contenir des dates, mais au moins une d'entre elles le devrait. Tous ces exemples que je voudrais corriger: '" "," "," 1/1/11 "," "," "," "," "," "' ' ' "", "", " "," 1/2/13 "," "," 4/3/2010 "," "," "' '" "," "," "," "," "," "," ", "1/3/2012" ' – hackbac

+0

J'écrivais un programme équivalent en utilisant' Text :: CSV' mais il a attiré mon attention sur le fait que vos données soient étranges en CSV. La fin des chaînes est soit '" ", =" 12345678 "' ou '" "," "=" 0987654 "'. Est-ce que l'un ou l'autre est correct? S'il vous plaît, expliquez. – Borodin

+0

Je me rends compte maintenant que vous avez déjà votre propre solution de travail, sauf que vous vous inquiétez du coût d'exécution de la substitution sur les enregistrements où tous les huit premiers champs sont déjà vides. S'il vous plaît, oubliez ces doutes. Non seulement cela brise la règle que vous devez écrire pour optimiser la clarté de votre code jusqu'à ce que vous trouviez que votre solution fonctionne trop lentement, mais je suis sûr que cela apportera également une amélioration négligeable des performances - surtout si vous lisez vos données à partir d'un fichier disque. – Borodin

Répondre

0

Merci pour tous vos commentaires. Je vais aller avec quelque chose comme ceci comme une solution:

use warnings; 
use Data::Dumper; 

my @case = (
     '"","","","1/2/2012","","","","",="12345678"', 
     '"","","1/1/11","","","","","",="12345678"', 
     '"","","","1/2/13","","4/3/2010","","",="987654"', 
     '"","","","","","","","1/3/2012",="567890"', 
     '"Add","New","1/1/2012","1/2/2012","","","","",="0987654"', 
     '"","","","","","","","",="91234567"' 
); 

my $argFind = (qr/^"","",("[\d\/]*",){6}/); 

my $replace = '"",' x 8; 

for (@case) { 
     unless (m/$replace/) { 
       s/$argFind/$replace/; 
     # Set flag to write file after loop 
     } 
} 

warn Dumper \@case; 
0

bien , J'ai obtenu votre résultat final avec ceci:

qr/^(?:"",){3}"\d\d?\/\d\d?\/\d{4}",(?:"",){4}/; 
  • Votre regex était désactivée car il y a 3 colonnes vides, et non 2.
  • Notez également que vous n'avez pas besoin de la capture générique à la fin pour la coller à nouveau.
  • Puisque la 4ème colonne n'était pas juste n'importe quel nombre de chiffres et de barres obliques, je cherche un modèle plus spécifique.
2

Je crois que vous devriez vraiment utiliser Text::CSV pour récupérer une liste de valeurs de données de l'enregistrement CSV. Ensuite, vous pouvez examiner les champs individuellement pour vérifier s'ils correspondent à vos besoins.

Mais tant que les données sont produites automatiquement et reste vous pourriez bien comportés essayer

qr[^(?: "",){2} (?: " (?: \d\d?/\d\d?/\d\d\d\d)? ",){6} ]x; 

whcih trouve deux champs vides suivis de six champs qui sont vides ou contenir quelque chose qui ressemble à une date. Ce programme démontre

use strict; 
use warnings; 

my @case = (
    '"","","","1/2/2012","","","","",="12345678"', 
    '"Add","New","1/1/2012","1/2/2012","","","",""="0987654"', 
    '"","","","","","","","",="91234567"' 
); 

my $argFind = qr[^(?: "",){2} (?: " (?: \d\d?/\d\d?/\d\d\d\d)? ",){6} ]x; 

my $replace = '"",' x 8; 

for (@case) { 
    print "$_\n" if s/$argFind/$replace/; 
} 

SORTIE

"","","","","","","","",="12345678" 
"","","","","","","","",="91234567" 

+0

+1 à cette réponse. Lorsque vous utilisez des fichiers CSV en utilisant un module est un must, ils sont douloureux et facile à briser. – AlfredoVR

+0

@ alfa64: sauf que cela ne semble pas être une sorte de CSV standard. Voir mon commentaire sur la question. – Borodin

Questions connexes