Bagaimana cara mengganti semua substring UTF-8 yang dikodekan persen dengan teks biasa UTF-8?

9

Saya punya file html dengan banyak teks UTF-8% -terkode dalam URL.

Misalnya "% D1% 80% D0% B5% D1% 81% D1% 83% D1% 80% D1% 81% D1% 8B" singkatan dari "ресурсы" ("sumber daya" dalam bahasa Rusia).

Tugasnya adalah untuk mengganti semua substring tersebut dengan teks UTF-8 yang dapat dibaca.

Untuk menyederhanakan tugas kami dapat mempertimbangkan tidak ada %penggunaan tanda lain dalam file. Digit huruf dapat berupa huruf besar dan kecil.

Saya menduga ini bisa dilakukan elegan dengan sed, perl, awkatau sesuatu tetapi tidak tahu bagaimana.

Aplikasi web ini sepertinya melakukan trik dengan teks yang Anda rekatkan di sana.

Ivan
sumber

Jawaban:

9

Dengan bash, zsh, gema GNU atau beberapa implementasi ksh pada beberapa sistem, ini dapat diterjemahkan hanya dengan echo -esetelah mengganti semua %dengan \x.

url_encoded_string="%D1%80%D0%B5%D1%81%D1%83%D1%80%D1%81%D1%8B"
temp_string=${url_encoded_string//%/\\x}

printf '%s\n' "$temp_string"
# output: \xD1\x80\xD0\xB5\xD1\x81\xD1\x83\xD1\x80\xD1\x81\xD1\x8B

echo -e "$temp_string"
# output: ресурсы

(Ini mengasumsikan string itu sendiri tidak mengandung karakter backslash dan bukan salah satu opsi yang didukung oleh echoperintah Anda )

Seperti yang ditunjukkan oleh @JoshLee, "peringatan gema" dapat dihindari dengan langsung menggunakan:

printf ${url_encoded_string//%/\\x}

alih-alih langsung di belakang perintah pertama.

LiuYan 刘 研
sumber
Perhatikan bahwa solusi elegan ini akan bekerja dengan pengkodean apa pun , bukan hanya UTF-8 (yaitu, singkirkan pengkodean untuk ~ dan lainnya. Trik lain untuk ditambahkan ke kotak alat saya. Terima kasih!
vonbrand
5

Dengan perl:

perl -pe 's/%([0-9A-F]{2})/pack"H2",$1/gei'

Atau dengan URI::Escape:

perl -MURI::Escape -pe '$_=uri_unescape$_'
Stéphane Chazelas
sumber
Saya suka ini karena saya dapat menyalurkannya apa pun yang saya inginkan berkat $_ gnu.org/software/bash/manual/html_node/Special-Parameters.html
Nemo
@Nemo, $_di sini adalah perl's $_, tidak bash' s. Dalam kombinasi dengan -popsi, ekspresi perl dijalankan untuk setiap catatan input (catatan dibaca dari file yang diberikan sebagai argumen atau stdin jika tidak ada argumen yang disediakan), dengan catatan saat ini disimpan di $_. Itu mirip dengan awk's $0.
Stéphane Chazelas
0

Ada program yang disebut convmvyang dapat membantu Anda.

Cukup gunakan convmv --unescape /some_path/target_file. Ini akan melakukan dry-run.

Setelah Anda mengkonfirmasi, gunakan convmv --notest --unescape /some_path/target_fileuntuk melanjutkan.

Homepage dari program ini adalah: http://j3e.de/linux/convmv/

Bintang Brilliant
sumber