Tira espaços após maiúsculas com sed

3

Eu estou escrevendo um script bash para gerar automaticamente alguns outros arquivos, e eu tenho que formatar algumas strings de uma certa 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 uma letra maiúscula. Por exemplo:

O S D Settings precisa se tornar OSD Settings

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

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

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

    
por SSumner 08.06.2012 / 19:49

4 respostas

1

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

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

Tudo isso faz é substituir os espaços que eu não quero com o sublinhado e, em seguida, exclui-los. Obrigado por todas as respostas!

    
por 11.06.2012 / 16:19
4

Isso cuida de nomes como A B Chadwick e A B C D'Souza

Texto como A B cde e A B CDE não são modificados.

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

:N e :S são rótulos ramificados para (qualquer nome servirá)
t e b são instruções de ramificação.
t ramificações após um substitemnt bem-sucedido no comando s/../../ anterior.
b ramifica-se incondicionalmente.

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

É complicado com sed , mas se perl estiver bem, você pode fazer desta maneira

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

Isso é difícil em sed porque não suporta afirmações de look-ahead.

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 malfeita com sed , tente

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

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

Testes:

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

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:]]\>\([^'\'']\|$\)\)/\n/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 deseja excluir e exclua o caractere escolhido por toda a string. \n é um bom candidato, pois não pode existir normalmente porque é usado pelo sed como delimitador de linha.

    
por 10.06.2012 / 10:26