2012-01-09 11 views
33

tôi sử dụng curl để nhận được một số phản ứng URL, đó là JSON phản ứng và nó chứa các ký tự unicode quốc gia thoát như \u0144 (ń)\u00f3 (ó).Làm thế nào để chuyển đổi uXXXX unicode sang UTF-8 sử dụng giao diện điều khiển các công cụ trong * nix

Làm cách nào để chuyển đổi chúng thành UTF-8 hoặc bất kỳ mã hóa nào khác để lưu vào tệp?

+1

Xem thêm Unix & Linux: ** [Trong bash, làm cách nào tôi có thể chuyển đổi Codecoint Unicode \ [0-9A-F \] thành ký tự inabale?] (Http: // unix .stackexchange.com/questions/12273) ** – hippietrail

Trả lời

26

Tôi không biết bạn đang sử dụng phân phối nào, nhưng cần bao gồm uni2ascii.

$ sudo apt-get install uni2ascii 

Nó chỉ phụ thuộc vào libc6, vì vậy nó là một giải pháp nhẹ (uni2ascii i386 4.18-2 là 55,0 kB trên Ubuntu)!

Sau đó, để sử dụng nó:

$ echo 'Character 1: \u0144, Character 2: \u00f3' | ascii2uni -a U -q 
Character 1: ń, Character 2: ó 
28

Có thể là một chút xấu xí, nhưng echo -e nên làm điều đó:

echo -en "$(curl $URL)" 

-e dịch thoát, -n ngăn chặn sự xuống dòng echo thường thêm.

Lưu ý: Công trình thoát \u trong công cụ xây dựng bash echo, nhưng không phải /usr/bin/echo.

Như đã nêu trong các nhận xét, đây là bash 4.2+ và 4.2.x có lỗi xử lý giá trị 0x00ff/17 (0x80-0xff).

+0

Tôi không nghĩ rằng '\ u' là chuỗi thoát được hỗ trợ. – cmbuckley

+1

@cbuckley Nó hoạt động cho tôi. – Kevin

+0

Zsh đó có phải là cơ hội không? Trong trường hợp đó, 's/support/thường được hỗ trợ /' :-) – cmbuckley

18

Giả sử \u luôn theo sau là chính xác 4 chữ số hex:

#!/usr/bin/perl 

use strict; 
use warnings; 

binmode(STDOUT, ':utf8'); 

while (<>) { 
    s/\\u([0-9a-fA-F]{4})/chr(hex($1))/eg; 
    print; 
} 

Các binmode đặt ra tiêu chuẩn thành UTF-8 chế độ. Lệnh s... thay thế mỗi lần xuất hiện của \u theo sau là 4 chữ số thập phân có ký tự tương ứng. Hậu tố e làm cho thay thế được đánh giá dưới dạng biểu thức thay vì được coi là chuỗi; số g nói để thay thế tất cả các lần xuất hiện thay vì chỉ là lần xuất hiện đầu tiên.

Bạn có thể lưu phần trên vào tệp ở đâu đó trong số $PATH của mình (đừng quên chmod +x). Nó lọc đầu vào tiêu chuẩn (hoặc một hoặc nhiều tệp được đặt tên trên dòng lệnh) thành đầu ra tiêu chuẩn.

+0

đơn giản và hiệu quả – rupps

+0

giải pháp tốt đẹp !! Tôi sẽ hack theo cách ngược lại từ [mã này] (http://icompile.eladkarako.com/yet-another-javascript-unicode-encodedecode/) sau này .. –

+0

Tại sao tôi nên mã hóa bất cứ điều gì để chuyển đổi từ một tiêu chuẩn khác? Bánh xe đã được phát minh ... –

8

Không dựa vào regexes: JSON có một số trường hợp góc lạ với \u các điểm mã thoát và không phải BMP. (cụ thể, JSON sẽ mã hóa một điểm mã bằng cách sử dụng hai\u thoát) Nếu bạn giả định 1 chuỗi thoát dịch sang 1 điểm mã, bạn sẽ phải chịu số phận trên văn bản đó.

Sử dụng JSON phân tích cú pháp đầy đủ từ ngôn ngữ của sự lựa chọn của bạn là đáng kể mạnh mẽ hơn:

$ echo '["foo bar \u0144\n"]' | python -c 'import json, sys; sys.stdout.write(json.load(sys.stdin)[0].encode("utf-8"))' 

Đó là thực sự chỉ ăn các dữ liệu để kịch bản này python ngắn:

import json 
import sys 

data = json.load(sys.stdin) 
data = data[0] # change this to find your string in the JSON 
sys.stdout.write(data.encode('utf-8')) 

Từ đó bạn có thể lưu dưới dạng foo.py và gọi số curl ... | foo.py

Ví dụ sẽ phá vỡ hầu hết các lần thử khác trong câu hỏi này là "\ud83d\udca3":

% printf '"\\ud83d\\udca3"' | python2 -c 'import json, sys; sys.stdout.write(json.load(sys.stdin)[0].encode("utf-8"))'; echo 

# echo will result in corrupt output: 
% echo -e $(printf '"\\ud83d\\udca3"') 
"������" 
# native2ascii won't even try (this is correct for its intended use case, however, just not ours): 
% printf '"\\ud83d\\udca3"' | native2ascii -encoding utf-8 -reverse 
"\ud83d\udca3" 
+0

Tại sao tôi nên mã hóa bất kỳ thứ gì để chuyển đổi từ một tiêu chuẩn này sang tiêu chuẩn khác? Bánh xe đã được phát minh ra ... –

+1

Thật kỳ lạ khi bạn đang xem xét lại điều này sau bốn năm. Câu trả lời này không, như bạn ngụ ý, tái tạo lại bánh xe: trên thực tế nó sử dụng trình phân tích cú pháp JSON dựng sẵn của Python. Nhiều câu trả lời khác trong chuỗi này cố gắng ép buộc một công cụ không nhằm mục đích này, và kết quả là, sẽ phát ra đầu ra sai trên một số đầu vào hợp lệ. Xem xét giá trị được mã hóa JSON '" \ ud83d \ udca9 "'; cả giải pháp bình chọn cao nhất sử dụng 'echo' và giải pháp' native2ascii' của bạn sẽ không xử lý đầu vào này. – Thanatos

+0

Tôi đã được thông báo về một số hoạt động về câu hỏi này. Đồng ý, rằng một số câu trả lời ở đây hút, Tuy nhiên, nếu tôi phải mã ngay cả 1 dòng thay vì sử dụng công cụ đã tồn tại tôi muốn gọi nó là phát minh lại bánh xe. Giải pháp của bạn được giới hạn trong nội dung JSON, bạn sẽ dịch nội dung không phải JSON như thế nào? Tôi đã nhận ra rằng giải pháp của bạn hoạt động cho tất cả các điểm mã, nhưng trong trường hợp của tôi giải pháp của bạn là cường điệu, tuy nhiên tôi thích ý tưởng phân tích cú pháp nhiều hơn 1 ký tự mã điểm. Câu trả lời được chấp nhận hiện tại hoạt động cho ví dụ của bạn (tuy nhiên nó không được in chính xác trên thiết bị đầu cuối của tôi, nhưng số "?" Giống nhau) –

8

sử dụng /usr/bin/printf "\u0160ini\u010di Ho\u0161i - A\u017e sa skon\u010d\u00ed zima" để có được chuyển đổi unicode-to-utf8 thích hợp.

+1

Một giải pháp hợp lệ, cho rằng câu hỏi liên quan đến Linux; chỉ là thông báo cho người dùng trên các nền tảng khác: không phải mọi tệp thực thi 'printf' bên ngoài đều hỗ trợ điều này (ví dụ: OS X 10.9.2 thì không). – mklement0

+0

FWIW tôi nghĩ rằng 'printf' có liên quan đến shell hiện tại bạn đang chạy, tức là. nó được coi là một trong những cấu trúc vỏ bọc ưa thích. Và tôi đang chạy hệ vỏ cá 2.7.1 trên macOS 10.12.6 và 'printf" \ u965 "' và bạn bè hoạt động tốt cho tôi. ✧ * 。٩ (ˊᗜˋ *) و✧ *。 – Chris

-1

Hoạt động trên Windows, nên làm việc trên * nix quá. Sử dụng python 2.

#!/usr/bin/env python 
from __future__ import unicode_literals 
import sys 
import json 
import codecs 

def unescape_json(fname_in, fname_out): 
    with file(fname_in, 'rb') as fin: 
     js = json.load(fin) 
    with codecs.open(fname_out, 'wb', 'utf-8') as fout: 
     json.dump(js, fout, ensure_ascii=False) 

def usage(): 
    print "Converts all \\uXXXX codes in json into utf-8" 
    print "Usage: .py infile outfile" 
    sys.exit(1) 

def main(): 
    try: 
     fname_in, fname_out = sys.argv[1:] 
    except Exception: 
     usage() 

    unescape_json(fname_in, fname_out) 
    print "Done." 

if __name__ == '__main__': 
    main() 
Các vấn đề liên quan