2009-07-22 11 views
6

Tengo un comando sed que quiero ejecutar en un archivo HTML enorme, terrible y feo que se creó a partir de un documento de Microsoft Word. Todo lo que debe hacer es eliminar cualquier instancia de la cadenaCoincidir con cualquier carácter (incluidas las líneas nuevas) en sed

style='text-align:center; color:blue; 
exampleStyle:exampleValue' 

El comando sed que estoy tratando de modificar es

sed "s/ style='[^']*'//" fileA > fileB 

Funciona muy bien, excepto que cada vez que hay una nueva línea dentro de la texto coincidente, no coincide. ¿Hay algún modificador para sed, o algo que pueda hacer para forzar el emparejamiento de cualquier personaje, incluidas las nuevas líneas?

Entiendo que las expresiones regulares son terribles en XML y HTML, blah blah blah, pero en este caso, los patrones de cadena están bien formados porque los atributos de estilo siempre comienzan con una sola comilla y terminan con una sola comilla. Entonces, si pudiera resolver el problema de la nueva línea, podría reducir el tamaño del HTML en más del 50% con solo un comando.


Al final, resultó que el script perl de Sinan Ünür funcionaba mejor. Fue casi instantáneo, y redujo el tamaño del archivo de 2.3 MB a 850k. Good ol 'Perl ...

+0

sed se basa en línea. Ese es el principal punto de parada aquí.Si usa el modificador/g regex, puede haber una opción de línea de comando para que lea el archivo como una sola 'línea', pero lo dudo (problemas de memoria y cosas por el estilo) –

+0

No hay opción (que yo sepa de) para leer un archivo como una sola línea. Usaría Perl para esto. – Dana

+0

Pero sed tiene los medios para agregar nuevas líneas en el espacio del patrón y el espacio de espera, por lo que es posible hacer un procesamiento de varias líneas en sed; simplemente no es bonito. – Beano

Respuesta

2

sed pasa el archivo de entrada línea por línea, lo que significa que, como yo entiendo, lo que quiere no es posible en sed.

podría utilizar el siguiente script Perl (no probado), sin embargo:

#!/usr/bin/perl 

use strict; 
use warnings; 

{ 
    local $/; # slurp mode 
    my $html = <>; 
    $html =~ s/ style='[^']*'//g; 
    print $html; 
} 

__END__ 

Un chiste sería:

$ perl -e 'local $/; $_ = <>; s/ style=\047[^\047]*\047//g; print' fileA > fileB 
1

Se podría eliminar todo el CR/LF usando tr, ejecute sed, y luego importar a un editor que auto-formatea.

3

Sed lee la entrada línea por línea, por lo que no es fácil hacer el procesamiento en una línea ... pero tampoco es imposible, necesita hacer uso de ramificación de sed. El siguiente trabajo, me han comentado que para explicar lo que está pasando (no la sintaxis más legible!):

sed "# if the line matches 'style='', then branch to label, 
    # otherwise process next line 
    /style='/b style 
    b 
    # the line contains 'style', try to do a replace 
    : style 
    s/ style='[^']*'// 
    # if the replace worked, then process next line 
    t 
    # otherwise append the next line to the pattern space and try again. 
    N 
    b style 
" fileA > fileB 
1

Puede probar esto:

awk '/style/&&/exampleValue/{ 
    gsub(/style.*exampleValue\047/,"") 
} 
/style/&&!/exampleValue/{  
    gsub(/style.* /,"") 
    f=1   
} 
f &&/exampleValue/{ 
    gsub(/.*exampleValue\047 /,"") 
    f=0 
} 
1 
' file 

Salida:

# more file 
this is a line 
    style='text-align:center; color:blue; exampleStyle:exampleValue' 
this is a line 
blah 
blah 
style='text-align:center; color:blue; 
exampleStyle:exampleValue' blah blah.... 

# ./test.sh 
this is a line 

this is a line 
blah 
blah 
blah blah.... 
+0

Este es mi voto a favor. La progresión de los lenguajes es sed -> awk -> C/C++/Ada. Comience por la izquierda y avance a la derecha hasta que tenga suficiente poder para hacer el trabajo. –

+0

puede no ser c/C++/Ada. IMO, tal vez Python/Perl/Ruby, etc., al menos para tareas de administrador de sistema. – ghostdog74

1

Otra forma es como:

$ cat toreplace.txt 
I want to make \ 
this into one line 

I also want to \ 
merge this line 

$ sed -e 'N;N;s/\\\n//g;P;D;' toreplace.txt 

salida:

I want to make this into one line 

I also want to merge this line 

Las cargas N otra línea, P imprime el espacio de patrones hasta el primer salto de línea, y D elimina el espacio de patrones hasta el primer salto de línea.

Cuestiones relacionadas