
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 Settings
necesita 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 Chadwick
yA B C D'Souza
Textos como A B cde
y A B CDE
no se modifican.
Utiliza dos caracteres nulos temporales \x00
para marcar los cambios (por nombre) a medida que avanza en una línea, eliminando espacios.
:N
y :S
sonsucursal aetiquetas (cualquier nombre servirá)
t
y b
son instrucciones de ramificación.
t
se ramifica tras un reemplazo exitoso en el s/../../
comando anterior.
b
sucursales 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 perl
está 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 sed
porque 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. \n
es 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!