sed: ignora los espacios en blanco iniciales al sustituir globalmente

sed: ignora los espacios en blanco iniciales al sustituir globalmente

Estoy intentando escribir un comando sed para sustituir espacios excesivos en un archivo. Cada palabra debe tener solo un espacio entre palabras, pero los espacios iniciales y las tabulaciones deben dejarse como están. Entonces el archivo:

     This is     an indented      paragraph. The   indentation   should not be changed.
This is the     second   line  of the    paragraph. 

Se convertirá:

     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

He probado variaciones de

/^[ \t]*/!s/[ \t]+/ /g

Cualquier idea sería apreciada.

Respuesta1

$ sed 's/\>[[:blank:]]\{1,\}/ /g' file
     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

La expresión que utilicé coincide con uno o varios [[:blank:]](espacios o tabulaciones)después de una palabray los reemplaza con un solo espacio. Coincide \>con el límite de ancho cero entre un carácter de palabra y un carácter que no es de palabra.

Esto fue probado con el nativo de OpenBSD sed, pero creo que debería funcionar sedtambién con GNU. GNU sedtambién lo utiliza \bpara hacer coincidir los límites de las palabras.

También puedes usar sed -Epara acortar esto a

sed -E 's/\>[[:blank:]]+/ /g' file

Nuevamente, si \>no te funciona con GNU sed, úsalo \ben su lugar.


Tenga en cuenta que, aunque lo anterior ordena el texto de ejemplo de la manera correcta, nobastantetrabajar para eliminar espacios después de la puntuación, como después de la primera oración en

     This is     an indented      paragraph.        The   indentation   should not be changed.
This is the     second   line  of the    paragraph.

Para eso, una variante un poco más complicada sería suficiente:

$ sed -E 's/([^[:blank:]])[[:blank:]]+/\1 /g' file
     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

Esto reemplaza cualquier carácter que no esté en blanco seguido de uno o más caracteres en blanco por el carácter que no esté en blanco y un solo espacio.

O bien, usando el estándar sed(y una optimización muy pequeña en el sentido de que solo hará la sustitución si haydos o másespacios/tabulaciones después de no espacios/tabulaciones),

$ sed 's/\([^[:blank:]]\)[[:blank:]]\{2,\}/\1 /g' file
     This is an indented paragraph. The indentation should not be changed.
This is the second line of the paragraph.

Respuesta2

POSIXly:

sed 's/\([^[:space:]]\)[[:space:]]\{1,\}/\1 /g; s/[[:space:]]*$//'

Que reemplaza cualquier secuencia de uno o más caracteres de espacio en blanco que siguen a un espacio que no es un espacio en blanco, con ese espacio que no es en blanco y un solo carácter SPC, y elimina los caracteres de espacio en blanco al final, lo que cubriría líneas en blanco y líneas con espacios en blanco al final (incluidos los CR que se encuentran en al final de las líneas provenientes de archivos de texto de Microsoft).

información relacionada