Apakah ada alternatif untuk sed yang mendukung unicode?

33

Sebagai contoh:

sed 's/\u0091//g' file1

Saat ini, saya harus lakukan hexdumpuntuk mendapatkan nomor hex dan dimasukkan ke dalam sedsebagai berikut:

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

Lalu:

$ sed 's/\xe9\xa6\x91//g' file1
A-letubby
sumber

Jawaban:

28

Cukup gunakan sintaks itu:

sed 's/馑//g' file1

Atau dalam bentuk lolos:

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

(Perhatikan bahwa versi Bash yang lebih lama dan beberapa shell tidak mengerti echo -e '\u9991', jadi periksa dulu.)

kekacauan
sumber
1
Apakah sed dihitung 馑 sebagai satu karakter atau 3? Yaitu, apakah echo 馑 | sed s/...//mencetak sesuatu?
user253751
@immibis Karena sedmemiliki pengubah g, ia menggantikan semua kejadian juga ketika mereka saling mengikuti. Juga sed harus menghitungnya sebagai satu karakter, lihat: echo -ne "馑" | wc -mmemberi 1. Jika Anda menghitung byte ( wc -c) itu akan kembali 3. Apakah saya memahami pertanyaan Anda dengan benar?
kekacauan
Maksud saya: apakah .berarti "satu karakter" atau "satu byte"?
user253751
@immibis saya cocok dengan satu karakter maka echo 馑 | sed s/...//memberi saya (tidak ada yang diganti)
chaos
4
@chaos: Ini berfungsi di bawah en_US.UTF-8, tetapi tidak di bawah C.
choroba
15

Perl dapat melakukan itu:

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

-CS menyalakan UTF-8 untuk input, output dan kesalahan standar.

choroba
sumber
7
Perl dapat melakukan hampir semua hal .....
wobbily_col
6

Sejumlah versi seddukungan Unicode :

  • Sed heirloom , yang didasarkan pada "bahan Unix asli".
  • GNU sed , yang merupakan basis kode sendiri.
  • Plan 9 sed , yang telah porting ke sistem operasi mirip Unix.

Saya tidak dapat menemukan informasi tentang BSD sed, yang saya pikir aneh, tetapi saya pikir kemungkinannya bagus karena mendukung Unicode juga. Sayangnya, tidak ada cara standar untuk mengetahui sedpengkodean mana yang akan digunakan, sehingga masing-masing melakukan ini dengan caranya sendiri.

Spooniest
sumber
Apakah mereka mendukung UTF-16 dengan dan tanpa BOM?
Bon Ami
10
UTF-16 sangat tidak dapat digunakan di OS berbasis Unix. Ini juga kekejian yang seharusnya tidak pernah melihat cahaya hari.
Brian Bi
Apakah mereka mendukung UTF-16 atau tidak tergantung pada implementasinya, dan saya khawatir saya tidak memiliki data itu. Saya ragu bahwa Plan 9 sed tidak (OS asli adalah UTF-8 di mana-mana), tapi saya tidak yakin, dan bahkan jika tidak, yang lain mungkin.
The Spooniest
2

Ini bekerja untuk saya:

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

Setetes lebih banyak kata daripada yang saya inginkan; inilah penjelasan lengkapnya:

  • -n nonaktifkan file swap vim
  • -E Ex mode ditingkatkan
  • -s mode diam
  • +'%s/\%u9991//g' jalankan perintah substitusi
  • +wq Simpan dan keluar
Aryeh Leib Taurog
sumber
Saya kira ini memodifikasi file1 di tempat , apakah itu benar?
Gerrit
@ kritik yang benar, dan terima kasih telah menunjukkannya.
Aryeh Leib Taurog
1

Dengan versi BASH terbaru, cukup hapus tanda kutip di sekitar ekspresi sed dan Anda dapat menggunakan string BASH yang lolos. Spasi dalam ekspresi sed atau bagian dari ekspresi sed yang mungkin ditafsirkan oleh BASH sebagai wildcard dapat dikutip secara individual.

$ echo "饥馑荐臻" | sed s/$'\u9991'//g
饥荐臻
Dave Rove
sumber
Ini harus menjadi jawaban yang diterima baru, sederhana dan bersih!
Allen Wang
0

Bekerja untuk saya dengan sed GNU (versi 4.2.1):

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

(Sebagai pengganti lain untuk sedAnda juga bisa menggunakan GNU awk; tetapi sepertinya tidak perlu.)

Janis
sumber