Китайские символы в переменной bash обрабатываются иначе, чем в файле - PullRequest
1 голос
/ 08 апреля 2019

Я получаю китайские символы в выходных данных curl и затем подаю их в качестве входных данных для скрипта Python, но я получаю два совершенно разных поведения в зависимости от того, как я обрабатываю символы.

Метод, который я предпочитаю, дает мне UnicodeEncodeError.

Предпочтительный метод:

read -r C < <(curl ...)
python3 -c "import sys, urllib.parse; \
            urllib.parse.quote(sys.argv[1])" "$C"
# UnicodeEncodeError: 'utf-8' codec can't encode character '\udce5' in position 0: surrogates not allowed

Альтернативный метод:

curl ... > tmp.txt
python3 -c "import urllib.parse; \
            with open('tmp.txt', encoding='utf-8') as f: \
                print(urllib.parse.quote(f.read()))"
# Outputs %E5%85%89%0A

Что я могу сделать, чтобы первый метод, который использует переменную bash, работал? Когда я echo $C или cat tmp.txt, китайский символ печатается правильно на моем терминале.

Когда я запускаю locale на моей машине, я получаю:

LANG=
LANGUAGE=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

EDIT Моя среда - гренки (на ChromeOS). Мой удар - GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu).

1 Ответ

0 голосов
/ 09 апреля 2019

Установите свой язык

python использует LC_CTYPE при интерпретации argv. форсировать локаль UTF8.

read -r C < <(curl ...)
LC_CTYPE='en_US.UTF8' python3 -c "import sys, urllib.parse; \
            print(urllib.parse.quote(sys.argv[1]))" "$C"

Альтернатива настройке LC_CTYPE, вы можете просто установить LANG, в зависимости от того, не используются ли другие части вашей системы LC_CTYPE.

или настройте его по умолчанию.

Установить локаль (при необходимости)

Если команда LC_CTYPE='en_US.UTF8' приводит к ошибке, возможно, у вас не установлен языковой стандарт en_US.UTF8 (или любой другой выбранный вами языковой стандарт).

Вы можете проверить, какие локали установлены, запустив locale -a. Чтобы установить локаль 'en_US.UTF8':

sudo locale-gen 'en_US'
sudo locale-gen 'en_US.UTF-8'
...