Китайские символы в переменной bash обрабатываются иначе, чем в файле

Я получаю китайские иероглифы в выводах 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=

РЕДАКТИРОВАТЬ Моя среда - крутон (в ChromeOS). Мой баш GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu).

Зачем завивать, когда вы можете запросить URL-адрес из Python?

Tomalak 08.04.2019 22:31

@Tomalak, возможно, это то направление, в котором я должен идти, но большая часть более крупной системы построена на сценариях bash, поэтому я не хотел переделывать. У вас есть идеи, почему я столкнулся с проблемой, опубликованной?

JellicleCat 08.04.2019 23:54

это сообщение об ошибке python сбивает с толку и сбивает с толку. если бы я мог понять, что это должно означать, я бы поднял отчет об ошибке.

Jasen 09.04.2019 06:41

«суррогаты не разрешены» просто означает, что кодирование суррогатных пар в UTF-8 недопустимо. Суть этих пар заключается в их использовании в UTF-16, где одна кодовая точка представлена ​​одним или двумя 16-битными значениями. Кстати, поиск этой ошибки приводит к нескольким совпадениям. Тем не менее, вам нужно извлечь минимальный воспроизводимый пример, потому что не совсем понятно, что именно у вас есть в какой момент. Кроме того, на какой ОС вы работаете? Это может быть важно, потому что передача аргументов и их кодировок зависит от ОС (и сложна).

Ulrich Eckhardt 09.04.2019 06:46

Как насчет того, чтобы избежать нежелательной обработки командной строки bash через curl | python и чтения sys.stdin в Python?

liborm 09.04.2019 10:29

@UlrichEckhardt, я нахожусь в среде крутонов на ChromeOS. Я добавил редактирование выше с некоторыми подробностями на случай, если это вас заинтересует.

JellicleCat 10.04.2019 01:05

@Tomalak, мне не удалось переместить все в Python, потому что я использую библиотеку nodejs для другой части системы, и попытка открыть подпроцесс для nodejs, снабжая его китайским иероглифом из Python, приводит к тому же результату UnicodeEncodeError .

JellicleCat 10.04.2019 20:10

Ваш код по-прежнему не позволяет воспроизвести проблему. Пожалуйста, прочитайте, что означает MCVE, и обратите внимание на мелкие детали.

Ulrich Eckhardt 15.04.2019 08:29
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
8
601
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Установите свой регион

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'

Спасибо, @Jasen, но даже ввод LC_CTYPE='en_US.UTF8' приводит к ошибке: -su: warning: setlocale: LC_CTYPE: cannot change locale (en_US.UTF8)

JellicleCat 10.04.2019 01:06

Возможно, вам потребуется установить эту локаль, возможно, спросите, как это сделать для Chrome-os в режиме суперпользователя.

Jasen 10.04.2019 05:43

Спасибо. Это дало мне понимание, чтобы пройти большой путь туда. Пожалуйста, извините за редактирование.

JellicleCat 10.04.2019 20:15

Другие вопросы по теме