2010-10-15 1 views
8

C'è un file dummy.txtCome faccio a sostituire con un'espressione valutata in Perl?

I contenuti sono:

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

devo cambiare la porzione mese (0,2,11) a +1, vale a dire, (1,3,12) ho scritto l'espressione regolare sostituzione come segue

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

si sta stampando

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

Come aggiungerlo - 3 numericamente rispetto alla stringa concat? ??

risposta

15

tre cambi:

  • dovrete utilizzare il modificatore di e per consentire l'espressione nella parte sostituzione.
  • Per effettuare la sostituzione a livello globale è necessario utilizzare il modificatore g. Questo è non è necessario se hai una data per riga.
  • si utilizza $1 sul lato sostituzione, non un backreference

Questo dovrebbe funzionare:

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

Anche se la regex contiene il delimitatore che si sta utilizzando (/ nel tuo caso), è meglio scegliere un diverso delimitatore ({} sopra), in questo modo non è necessario sfuggire al delimitatore nella regex rendendo la regex pulita.

+0

fantastico !, ha funzionato - se non ti dispiace puoi spiegare la sintassi s {} - voglio dire è possibile ottenerlo con s/piuttosto che s { – Sekhar

+2

@OP: ho aggiornato la mia risposta. 's ///' è equivalente a 's {} {}', solo che usa un delimitatore diverso e ti salverà dall'escludere quelli '/'. – codaddict

+0

Anche se non richiesto, l'uso del modificatore 'x' per le espressioni regolari ne migliora notevolmente la leggibilità: s {/ (\ d +) /} {'/'. ($ 1 + 1).'/'} egx –

1

Che ne dici di questo?

$ 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

grazie per questo approccio - Continuerò ad esplorare perl - Ho accettato un'altra risposta in quanto risolve con una singola riga – Sekhar

+0

Sì, quelle risposte sono decisamente migliori, non conoscevo nemmeno le espressioni. – Lazer

0

questo funziona: (e è quello di valutare la stringa di sostituzione: vedere la documentazione perlrequick).

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

print $line; 

Aiuta ad utilizzare ! o qualche altro carattere come delimitatore se l'espressione regolare ha / stessa.


è anche possibile utilizzare, da questa domanda in Can Perl string interpolation perform any expression evaluation?

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

print $line; 

ma se questa è una domanda compiti a casa, essere pronti a spiegare quando l'insegnante si chiede come si raggiunge questa soluzione.

+0

Grazie per aver menzionato il carattere delimitatore! – Sekhar

+0

oh no no !, non una domanda per i compiti a casa, te lo spiegherò - la mia soluzione ha funzionato, ma mi chiedo se c'è un approccio migliore. Sto creando un database di tracciamento di tutti gli utenti che hanno utilizzato un'applicazione. Il sistema di autenticazione è esterno, tuttavia scrive un file separato per ogni accesso. Sto cercando di ottenere il tempo di accesso acquisendo l'ora di creazione del file e inserendo nel formato DATETIME di SQL Server. Il mio primo programma perl che ho scritto mi è sfuggito di questo fatto importante, quindi la maggior parte delle date erano in formato 0/0/2010 (incompatibile con DATETIME). eseguire nuovamente il programma Perl con modifiche era costoso – Sekhar