Quitar espacios después de letras mayúsculas individuales con sed

Quitar espacios después de letras mayúsculas individuales con sed

Estoy escribiendo un script bash para generar automáticamente otros archivos y tengo que formatear algunas cadenas de cierta manera. Específicamente, el último problema que tengo es formatear una cadena que tiene letras mayúsculas individuales y una palabra que comienza con letra mayúscula. Por ejemplo:

O S D Settingsnecesita convertirseOSD Settings

Tengo un comando sed que elimina el primer espacio, pero también elimina la "D" (es decir, O S D Settings-> OS Settings). Este comando es:

O S D Settings | sed 's/ \([A-Z]\)* \(A-Za-z]*\)/\1/g'

¿Alguien sabe cómo eliminar los espacios entre letras mayúsculas individuales sin perder ninguna letra?

Respuesta1

Esto se ocupa de nombres como A B ChadwickyA B C D'Souza

Textos como A B cdey A B CDEno se modifican.

Utiliza dos caracteres nulos temporales \x00para marcar los cambios (por nombre) a medida que avanza en una línea, eliminando espacios.

:Ny :Ssonsucursal aetiquetas (cualquier nombre servirá)
ty bson instrucciones de ramificación.
tse ramifica tras un reemplazo exitoso en el s/../../comando anterior.
bsucursales incondicionalmente.

sed -r ":N                                                # loop per name
         /(\<[A-Z]\> )+[A-Z][a-z']/{                      # line needs action
             s/((\<[A-Z]\> )+)([A-Z][a-z'])/\x00\1\x00\3/ # add \x00 markers
            :S                                            # loop per space
             s/(\x00[A-Z]+) (\<[A-Z]\>)/\1\2/             # delete a space
             t S                                          # any more spaces? 
             b N                                          # any more names?
         }; s/\x00//g"                                    # remove \x00

Respuesta2

Es complicado sed, pero si perlestá bien, puedes hacerlo de esta manera.

echo O S D Settings | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'

Esto es difícil sedporque no admite afirmaciones anticipadas.

Pruebas:

echo O S D | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo O S D Settings | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo O S D. | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo One O DDE T. S Asdf Q R Tee | perl -p -e 's/(\b[A-Z]) (?=.([^\w]|$))/$1/g'
echo O S D\  | perl -p -e 's/([A-Z]) (?=.([^\w]|$))/$1/g'

Si quieres una solución descuidada sed, prueba

echo O S D Settings | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'

Lo que funciona para su muestra, pero fallará en otros casos.

Pruebas:

echo O S D | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo O S D Settings | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo O S D. | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo One O DDE T. S Asdf Q R Tee | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'
echo O S D\  | sed -e 's/ \([A-Z]\) \([A-Z] \)/\1\2/g'

Respuesta3

Esto podría funcionar para usted:

echo "O S D Settings and B T W and A B C D'Souza too F Y I" |
sed ':a;s/\(\<[[:upper:]]\>\) \(\<[[:upper:]]\>\([^'\'']\|$\)\)/\1\n\2/g;ta;s/\n//g'
OSD Settings and BTW and ABC D'Souza too FYI

Explicación:

Utilice un carácter que no exista en la cadena original para reemplazar los espacios que desea eliminar, luego elimine ese carácter elegido en toda la cadena. \nes un buen candidato ya que no puede existir normalmente porque sed lo utiliza como delimitador de línea.

Respuesta4

Terminé usando sed con pipes para obtener una declaración que me resulte fácil de entender:

echo O S D Settings | sed 's/\([A-Z][^ ]\)/_\1/g' | sed 's/ //g' | sed 's/_/ /g'

Todo lo que esto hace es reemplazar los espacios que no quiero con el guión bajo y luego los elimina. ¡Gracias por todas las respuestas!

información relacionada