Jak usunąć zduplikowane znaki?

18

Jeśli mam linię jako:

Thhiisss iisss mmyyy nameeee

Chcę to wydrukować jako:

This is my name

Jakie jest do tego polecenie unix?

krishna
źródło
Czy możesz podać więcej kontekstu na temat pochodzenia duplikatów i pożądanych wyników? Co jeśli „Mmyyy nameee iisss Jesssssiiieee”?
Paulo Almeida

Odpowiedzi:

24

Z tr:

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

Objaśnienie: -sPrzełącznik tr„ściska” powtarza znaki. Jak pokazano, przełącznik może być używany z szeregiem znaków: ado z.

mkc
źródło
2
wyjaśnienie tego polecenia może być pomocne dla przyszłych czytelników.
Geek
8

W systemie GNU musisz użyć tego sedlub podobnego, jeśli twoje ustawienia regionalne używają znaków wielobajtowych ( jak sugeruje jimmij ), ponieważ GNU trmoże odwoływać się tylko do znaku na bajt. W ustawieniach ASCII możesz usunąć wszystkie duplikaty w / trlike:

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

Więc...

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

... drukuje ...

This is my name

Możesz to również zrobić selektywnie, odnosząc się do swoich celów według zakresu:

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

...lub...

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

... które okazują się być tym samym i które oba drukują:

Thhiisss iisss mmyyy nameeee

... lub wykorzystanie [:punct:], [:digit:], [:lower:], [:alpha:]lub cokolwiek chce. Możesz także negować wybór w / -cso ...

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

... drukuje ...

TTTThis is my name
mikeserv
źródło
7

Jeden sposób z sed:

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

lub nawet prościej:

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

(dzięki Costas i mikeserv za komentarze).

jimmij
źródło
sed 's/\(.\)\1\+/\1/g'
Costas
3

Spróbuj tr:

echo "Thhiisss iisss mmyyy nameeee" | tr -s 'hismye'
heemayl
źródło