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

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.)


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.


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.


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ź

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
饥荐臻

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).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.