2009-11-30 13 views
11

De forma predeterminada, Perl imprime \ r \ n en un entorno win32. ¿Cómo puedo anular esto? Estoy usando Perl para hacer algunos cambios en algún código fuente en un repositorio, y no quiero cambiar todos los caracteres de nueva línea.¿Cómo puedo imprimir solo una nueva línea de Unix en Perl en Win32?

Intenté cambiar el separador de registros de salida pero sin suerte.

Gracias!

Editar: quería incluir un ejemplo de código - Estoy haciendo una búsqueda y reemplazo durante algunos archivos que siguen un patrón relativamente sencillo como esto:

#!/usr/bin/perl 
# test.pl 

use strict; 
use warnings; 

$/ = undef; 
$\ = "\n"; 
$^I=".old~"; 

while (<>) { 
    while (s/hello/world/) { 

    } 
    print; 
} 

Esto debe reemplazar todas las instancias de "hola "con" mundo "para cualquier archivo pasado en la línea de cmd.

Edición 2: probé el binmode como se sugiere sin ninguna suerte inicialmente. Profundicé un poco más y descubrí que $^I (la variable especial de edición in place) estaba anulando binmode. ¿Hay algún trabajo para poder usar la edición en el lugar?

Datos 3: Como Sinan señala a continuación, que necesitaba usar binmode ARGVOUT con $^I en lugar de binmode STDOUT en mi ejemplo. Gracias.

+2

Si cambió el separador de registros de salida, entonces eso fue lo único que puede hacer. Supongo que cometió otro error (como no dividir correctamente las líneas entrantes o no masticarlas). –

+0

¿Puedes dar un ejemplo de algún código que imprime '\ r \ n' cuando no lo quieres? – Ether

+0

@Sinan, ¿por qué asumirías que no estoy dispuesto? No estoy dispuesto. No tengo un guion corto a mano. Tengo un guión muy largo y complicado que probablemente no tendrá mucho sentido y sería aún más confuso. Puedo hacer una versión abreviada más tarde esta noche. Pensé que estaba incluyendo las partes relevantes. No sabía que la edición in situ era relevante en ese momento. Gracias. –

Respuesta

12

impresión "\n" a un gestor de archivo en Windows emite, por defecto, un CARRIAGE RETURN ("\015") seguido de un LINE FEED ("\012") debido a que el carácter de nueva línea secuencia estándar en Windows.

Esto ocurre de forma transparente, por lo que necesita anularla para el gestor de archivo especial ARGVOUT (ver perldoc perlvar):

#!/usr/bin/perl -i.bak 

use strict; use warnings; 

local ($\, $/); 

while (<>) { 
    binmode ARGVOUT; 
    print; 
} 

Salida:

 
C:\Temp> xxd test.txt 
0000000: 7465 7374 0d0a 0d0a      test.... 

C:\Temp> h test.txt 

C:\Temp> xxd test.txt 
0000000: 7465 7374 0a0a       test.. 

Véase también perldoc open, perldoc binmode y perldoc perliol (gracias daotoad)

+5

No es realmente el \ n el que hace nada. Es la traducción filehandle \ 012. Es decir, sin escribir en un identificador de archivo de texto, \ n sigue siendo \ 012. –

+0

@brian d foy: Aclaración agregada. –

+2

Para una discusión detallada de las capas Perl IO, el mecanismo que hace esta traducción, consulte perlol perlol - http://perldoc.perl.org/perliol.html – daotoad

4

¿El binmode(STDOUT) trabajo?

+0

+1, sí, parcialmente ... ver edición. Gracias. –

0

Una nueva línea UNIX es un personaje LINEFEED, que es el código ASCII 10.

print "\012";

+1

En Windows: 'perl -e" imprime qq {\ 012} "| xxd' produce '0000000: 0d0a' a menos que establezca' binmode STDOUT'. –

+1

No es un problema obtener el personaje correcto. Es la traducción en modo de texto que está modificando la salida mientras se escribe en un manejador de archivo de texto. –

+0

gracias por corregirme en Windows; Había olvidado que Perl "ayudó" incluso cuando se le dijo explícitamente qué hacer. –

0

Los datos que usted está leyendo en contiene los finales de línea, por lo que está recibiendo de vuelta de nuevo.Puede despojarlos de ti mismo con chomp, a continuación, añadir su propio final de vuelta, a condición de que haya configurado binmode como se describe Sinan ::

while (<>) { 
    binmode; 
    chomp;  # strip off \r\n 
    while (s/search/replace/) { 
     # ... 
    } 
    print; 
    print "\n"; # add your own line ending back 
} 
1

Re: pregunta sobre la binmode se pierde cuando $^I abre una nueva asa de salida, se podría solucionar esto con el open pragma:

use open OUT => ':raw'; 

lo que obligará a todos los controladores de archivo abierto para escritura a tener la ': crudo' capa PerlIO (equivalente a binmode sin argumentos) para aplicar a ellos. Solo tenga cuidado si está abriendo algo else para la salida que aplique :crlf o cualquier otra capa según sea necesario.

Cuestiones relacionadas