2010-10-15 3 views
8

Il y a un fichier dummy.txtComment remplacer une expression évaluée dans Perl?

Le contenu sont:

9/0/2010 
9/2/2010 
10/11/2010 

Je dois changer la partie mois (0,2,11) à +1, à savoir (1,3,12) J'ai écrit le regex de substitution comme suit

$line =~ s/\/(\d+)\//\/\1+1\//; 

Il est imprime

9/0+1/2010 
9/2+1/2010 
10/11+1/2010 

Comment le faire ajouter - 3 numériquement que d'effectuer une concat? ??

Répondre

15

Trois changements:

  • Vous devrez utiliser le modificateur e pour permettre une expression dans la pièce de rechange . Pour faire le remplacement global vous devez utiliser le modificateur g. C'est pas nécessaire si vous avez une date par ligne.
  • Vous utilisez $1 du côté de remplacement, pas un backreference

Cela devrait fonctionner:

$line =~ s{/(\d+)/}{'/'.($1+1).'/'}eg; 

Aussi, si votre regex contient le délimiteur que vous utilisez (/ dans votre cas), il est mieux de choisir un délimiteur différent ({} ci-dessus), de cette façon vous n'avez pas besoin d'échapper le délimiteur dans l'expression régulière ce qui rend votre regex propre.

+0

awesome !, cela a fonctionné - si cela ne vous dérange pas pouvez-vous expliquer la syntaxe s {} - je veux dire est-il possible de l'obtenir avec s/plutôt que s { – Sekhar

+2

@OP: J'ai mis à jour ma réponse. 's ///' est équivalent à 's {} {}', juste qu'il utilise un délimiteur différent et vous évitera d'échapper '/'. – codaddict

+0

Bien que cela ne soit pas obligatoire, l'utilisation du modificateur 'x' pour vos expressions régulières améliore considérablement leur lisibilité: s {/ (\ d +) /} {'/'. (1 $ + 1).'/'} egx –

1

Que pensez-vous de cela?

$ cat date.txt 
9/0/2010 
9/2/2010 
10/11/2010 
$ perl chdate.pl 
9/1/2010 
9/3/2010 
10/12/2010 
$ cat chdate.pl 
use strict; 
use warnings; 

open my $fp, '<', "date.txt" or die $!; 

while (<$fp>) { 
    chomp; 
    my @arr = split (/\//, $_); 
    my $temp = $arr[1]+1; 
    print "$arr[0]/$temp/$arr[2]\n"; 
} 

close $fp; 
$ 
+0

merci pour cette approche - je vais continuer à explorer perl - j'ai accepté une autre réponse car elle résout avec une seule ligne – Sekhar

+0

Oui, ces réponses sont certainement mieux, je ne savais pas sur les expressions non plus. – Lazer

0

cela fonctionne: (e est d'évaluer la chaîne de remplacement: consultez la documentation perlrequick).

$line = '8/10/2010'; 
$line =~ s!/(\d+)/!('/'.($1+1).'/')!e; 

print $line; 

Il aide à utiliser ! ou un autre caractère comme séparateur si l'expression régulière a / lui-même.


Vous pouvez également utiliser, à partir de cette question dans Can Perl string interpolation perform any expression evaluation?

$line = '8/10/2010'; 
$line =~ s!/(\d+)/!("/@{[$1+1]}/")!e; 

print $line; 

mais si cela est une question de devoirs, être prêt à expliquer quand l'enseignant vous demande comment vous arrivez à cette solution.

+0

Merci d'avoir mentionné le caractère délimiteur! – Sekhar

+0

oh non non !, pas une question de devoirs, je vais vous l'expliquer - ma solution a fonctionné mais je me demande s'il y a une meilleure approche. Je crée une base de données de suivi de tous les utilisateurs qui ont utilisé une application. Le système d'authentification est externe - mais il écrit un fichier séparé pour chaque connexion. J'essaye d'obtenir l'heure de connexion en capturant l'heure de création de fichier et insérez dans le format de SQL Server DATETIME. Mon premier programme perl que j'ai écrit a manqué ce fait important - donc la plupart des dates étaient au format 0/0/2010 (Incompatible avec DATETIME). exécuter le programme Perl à nouveau avec des changements était coûteux – Sekhar

Questions connexes