Como remover caracteres duplicados?

18

Se estou tendo uma linha como:

Thhiisss iisss mmyyy nameeee

Quero imprimir isso como:

This is my name

Qual é o comando unix para isso?

Krishna
fonte
Você pode fornecer um pouco mais de contexto sobre a origem das duplicações e a saída desejada? E se "Mmyyy nameee iisss Jesssssiiieee"?
Paulo Almeida

Respostas:

24

Com tr:

echo "Thhiisss iisss mmyyy nameeee" | tr -s 'a-z'

Explicação: A -sopção de tr"espremer" caracteres repetidos. Como mostrado, o switch pode ser usado com um intervalo de caracteres: apara z.

mkc
fonte
2
alguma explicação para o comando pode ser útil para futuros leitores.
Geek
8

Em um sistema GNU, você precisará usar sedou semelhante se o seu código do idioma usar caracteres multibyte ( como jimmij sugere ) porque o GNU trpode fazer referência apenas a um caractere por byte. Em um código de idioma ASCII, você pode remover todas as duplicatas com tr:

LC_ALL=C tr -s '\0-\255' <input

Então...

echo Thhiisss iisss mmyyy nameeee|
LC_ALL=C tr -s '\0-\255'

... imprime ...

This is my name

Você também pode fazer isso de forma seletiva consultando seus destinos por intervalo:

echo TThhiisss iisss mmyyy nameeee|
LC_ALL=C tr -s '\101-\132'

...ou...

echo TTTThhiisss iisss mmyyy nameeee|
LC_ALL=C tr -s '[:upper:]'

... que funcionam da mesma forma e que imprimem:

Thhiisss iisss mmyyy nameeee

... ou utilização [:punct:], [:digit:], [:lower:], [:alpha:]ou o que quer que você gostaria. Você também pode negar a seleção w / -cso ...

echo 'TTTThhiisss     iisss mmyyy nameeee' |
LC_ALL=C tr -cs '[:upper:]'

... imprime ...

TTTThis is my name
mikeserv
fonte
7

Uma maneira com sed:

sed ':X;s/\(.\)\1/\1/g;tX'

ou ainda mais simples:

sed 's/\(.\)\1*/\1/g'

(obrigado Costas e mikeserv pelos comentários).

jimmij
fonte
sed 's/\(.\)\1\+/\1/g'
Costas
3

Tente tr:

echo "Thhiisss iisss mmyyy nameeee" | tr -s 'hismye'
heemail
fonte