Remova os espaços após letras maiúsculas com sed

Remova os espaços após letras maiúsculas com sed

Estou escrevendo um script bash para gerar automaticamente alguns outros arquivos e preciso formatar algumas strings de uma determinada maneira. Especificamente, o último problema que estou tendo é a formatação de uma string que possui letras maiúsculas individuais e uma palavra que começa com letra maiúscula. Por exemplo:

O S D Settingsprecisa se tornarOSD Settings

Eu tenho um comando sed que remove o primeiro espaço, mas também exclui o "D" (ou seja, O S D Settings-> OS Settings). Este comando é:

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

Alguém sabe como excluir os espaços entre as letras maiúsculas individuais sem perder nenhuma letra?

Responder1

Isso cuida de nomes como A B ChadwickeA B C D'Souza

Textos como A B cdee A B CDEnão são modificados.

Ele usa dois caracteres nulos temporários \x00para marcar alterações (por nome) à medida que avança em uma linha, removendo espaços.

:Ne :Ssãoramificar pararótulos (qualquer nome serve)
te bsão instruções de ramificação.
tramifica após uma substituição bem-sucedida no s/../../comando anterior.
bramos 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

Responder2

É complicado com sed, mas se perlestiver tudo bem, você pode fazer desta maneira

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

Isso é difícil sedporque não suporta afirmações antecipadas.

Testes:

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'

Se você quiser uma solução desleixada sed, tente

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

O que funciona para sua amostra, mas falhará em outros casos.

Testes:

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'

Responder3

Isso pode funcionar para você:

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

Explicação:

Use um caractere que não exista na string original para substituir os espaços que você deseja excluir e, em seguida, exclua o caractere escolhido em toda a string. \né um bom candidato, pois não pode existir normalmente porque é usado pelo sed como delimitador de linha.

Responder4

Acabei usando apenas sed com pipes para obter uma declaração que seja fácil de entender:

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

Tudo o que isso faz é substituir os espaços que não quero pelo sublinhado e depois excluí-los. Obrigado por todas as respostas!

informação relacionada