Czy istnieje alternatywa dla sed, która obsługuje Unicode?

33

Na przykład:

sed 's/\u0091//g' file1

W tej chwili muszę zrobić, hexdumpaby uzyskać numer szesnastkowy i wpisać w sednastępujący sposób:

$ echo -ne '\u9991' | hexdump -C
00000000  e9 a6 91                                          |...|
00000003

I wtedy:

$ sed 's/\xe9\xa6\x91//g' file1
A-letubby
źródło

Odpowiedzi:

28

Po prostu użyj tej składni:

sed 's/馑//g' file1

Lub w postaci ucieczki:

sed "s/$(echo -ne '\u9991')//g" file1

(Pamiętaj, że starsze wersje Bash i niektóre powłoki nie rozumieją echo -e '\u9991', więc sprawdź najpierw.)

chaos
źródło
1
Czy sed liczy się jako jeden znak czy 3? Czy echo 馑 | sed s/...//coś drukuje?
user253751
@immibis Ponieważ sedma modyfikator g, zastępuje wszystkie wystąpienia również wtedy, gdy podążają one za sobą. Również sed powinien liczyć się jako jedna postać, patrz: echo -ne "馑" | wc -mdaje 1. Jeśli policzysz bajty ( wc -c), to zwróci 3. Czy dobrze zrozumiałem twoje pytanie?
chaos
Miałem na myśli: czy .oznacza „jeden znak” czy „jeden bajt”?
user253751 17.04.15
@immibis I pasuje do jednej postaci, dlatego echo 馑 | sed s/...//daje mi (nic nie jest zamieniane)
chaos
4
@chaos: Działa poniżej en_US.UTF-8, ale nie działa C.
choroba
15

Perl może to zrobić:

echo 汉典“馑”字的基本解释 | perl -CS -pe 's/\N{U+9991}/Jin/g'

-CS włącza UTF-8 dla standardowego wejścia, wyjścia i błędu.

choroba
źródło
7
Perl może zrobić prawie wszystko ...
wobbily_col
6

Wiele wersji sedobsługi Unicode :

  • Heirloom sed , oparty na „oryginalnym materiale uniksowym”.
  • GNU sed , który jest własną bazą kodu.
  • Plan 9 sed , który został przeniesiony do systemów operacyjnych typu Unix.

Nie mogłem znaleźć informacji na temat BSD sed, co moim zdaniem było dziwne, ale myślę, że szanse są duże, że obsługuje także Unicode. Niestety nie ma standardowego sposobu na określenie, sedktórego kodowania użyć, więc każdy robi to na swój własny sposób.

The Spooniest
źródło
Czy obsługują UTF-16 z BOM i bez BOM?
Bon Ami
10
UTF-16 jest dość bezużyteczny w systemach operacyjnych opartych na Uniksie. To także obrzydliwość, która nigdy nie powinna ujrzeć światła dziennego.
Brian Bi
To, czy obsługują UTF-16, zależy od implementacji i obawiam się, że nie mam tych danych. Wątpię, czy tak działa Plan 9 (oryginalny system operacyjny to UTF-8 wszędzie), ale nie jestem pewien, a nawet jeśli nie, inni mogą.
Spooniest
2

To działa dla mnie:

$ vim -nEs +'%s/\%u9991//g' +wq file1

To kropla bardziej gadatliwa, niż bym chciał; oto pełne wyjaśnienie:

  • -n wyłącz plik wymiany vim
  • -E Ex ulepszony tryb
  • -s tryb cichy
  • +'%s/\%u9991//g' wykonać polecenie podstawienia
  • +wq Zapisz i wyjdź
Aryeh Leib Taurog
źródło
Przypuszczam, że to zmienia file1 na miejscu , czy to prawda?
gerrit
@gerrit to prawda i dziękuję za zwrócenie na to uwagi.
Aryeh Leib Taurog
1

W najnowszych wersjach BASH po prostu pomiń cudzysłowy wokół wyrażenia sed i możesz użyć znaków ucieczki BASH. Odstępy w obrębie wyrażenia sed lub części wyrażenia sed, które mogą być interpretowane przez BASH jako znaki wieloznaczne, które można indywidualnie cytować.

$ echo "饥馑荐臻" | sed s/$'\u9991'//g
饥荐臻
Dave Rove
źródło
To powinna być nowa zaakceptowana odpowiedź, prosta i czysta!
Allen Wang
0

Działa dla mnie z GNU sed (wersja 4.2.1):

$ echo -ne $'\u9991' | sed 's/\xe9\xa6\x91//g' | hexdump -C
$ echo -ne $'\u9991' | hexdump -C
00000000  e9 a6 91

(Jako kolejny zamiennik sedmożesz również użyć GNU awk; ale nie wydaje się to konieczne).

Janis
źródło