2010-10-15 19 views
8

Hay un archivo dummy.txt¿Cómo puedo sustituir con una expresión evaluada en Perl?

Los contenidos son:

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

tengo que cambiar la parte correspondiente al mes (0,2,11) a 1, es decir, (1,3,12) escribí la expresión regular la sustitución de la siguiente manera

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

se está imprimiendo

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

¿Cómo hacer que se agregue - 3 numéricamente que realizar cadena concat? ??

Respuesta

15

tres cambios:

  • que tendrá que utilizar el modificador e para permitir una expresión en la parte reemplazo.
  • Para hacer la sustitución globalmente debe usar el modificador g. Esto es no necesario si tiene una fecha por línea.
  • Se utilizan $1 en el lado de reemplazo, no una referencia inversa

Esto debería funcionar:

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

Además, si su expresión regular contiene el delimitador que está usando (/ en su caso), es es mejor elegir un delimitador diferente ({} arriba), de esta manera no tiene que escapar del delimitador en la expresión regular para limpiar su expresión regular.

+0

¡genial! Funcionó. Si no te importa, puedes explicar la sintaxis de s {}. Quiero decir que es posible lograrlo con s/rather than s { – Sekhar

+2

@OP: actualicé mi respuesta. 's ///' es equivalente a 's {} {}', solo que usa un delimitador diferente y le evitará escapar de '/'. – codaddict

+0

Si bien no es obligatorio, el uso del modificador 'x' para las expresiones regulares mejora en gran medida su legibilidad: s {/ (\ d +) /} {'/'. ($ 1 + 1).'/'} egx –

1

¿Qué le parece esto?

$ 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

gracias por este enfoque - Seguiré explorando Perl - He aceptado otra respuesta, ya que resuelve con una sola línea – Sekhar

+0

Sí, esas respuestas son definitivamente mejores, yo tampoco sabía de expresiones. – Lazer

0

esto funciona: (e es la evaluación de la cadena de reemplazo: consulte la documentación perlrequick).

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

print $line; 

Ayuda a utilizar ! o algún otro carácter como delimitador si su expresión regular tiene / sí.


También puede utilizar, a partir de esta pregunta en Can Perl string interpolation perform any expression evaluation?

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

print $line; 

pero si esto es una pregunta tarea, estar dispuestos a explicar cuando el maestro le pregunta cómo llegar a esta solución.

+0

¡Gracias por mencionar el carácter delimitador! – Sekhar

+0

¡oh no no !, no es una pregunta para la tarea, se lo explicaré, mi solución funcionó, pero me pregunto si hay un mejor enfoque. Estoy creando una base de datos de seguimiento de todos los usuarios que han usado una aplicación. El sistema de autenticación es externo; sin embargo, escribe un archivo separado para cada inicio de sesión. Estoy intentando obtener el tiempo de inicio de sesión capturando el tiempo de creación de archivo e inserto en el formato DATETIME de SQL Server. Mi primer programa de perl que escribí omitió este hecho importante, por lo que la mayoría de las fechas estaban en formato 0/0/2010 (incompatible con DATETIME). ejecutar el programa Perl nuevamente con cambios fue costoso – Sekhar

Cuestiones relacionadas