Пример команды, которая демонстрирует симптом: sed 's/./@/' <<<$'\xfc'терпит неудачу, потому что байт 0xfcне является допустимым символом UTF-8.
Обратите внимание, что, напротив, GNU sed (Linux, но также устанавливается на macOS) просто пропускает недействительный байт, не сообщая об ошибке.
Использование ранее принятого ответа - вариант, если вы не против потерять поддержку своего истинного языка (если вы работаете в системе США и вам никогда не нужно иметь дело с иностранными символами, это может быть хорошо).
Однако тот же эффект можно получить Ad-Hoc для одной команды только :
LC_ALL=C sed -i "" 's|"iphoneos-cross","llvm-gcc:-O3|"iphoneos-cross","clang:-Os|g' Configure
Примечание: важен эффективный LC_CTYPE параметр C, поэтому LC_CTYPE=C sed ...он также обычно работает, но если LC_ALLон установлен (что-то иное, чем C), он переопределит отдельные LC_*переменные -категории, такие как LC_CTYPE. Таким образом, наиболее надежный подход заключается в установке LC_ALL.
Тем не менее, (фактически) настройки LC_CTYPEдля Cобрабатывают строки , как если бы каждый байт был свой характер ( не интерпретации , основанная на правилах кодирования выполняется), причем без учета для - многобайтового по требованию - UTF-8 , кодирующие , что OS X использует по умолчанию где иностранные символы имеют многобайтовые кодировки .
В двух словах: заходящих LC_CTYPEнаC причины оболочку и утилиты только распознавать основные английские буквы как буквы (те , в 7-битном диапазоне ASCII), так что иностранные гольцы. не будут рассматриваться как буквы , что приведет, например, к неудачному преобразованию в верхний / нижний регистр.
Опять же, это может быть хорошо, если вам не нужно сопоставлять многобайтовые символы, такие как é, и просто хотите пропустить такие символы .
Если этого недостаточно и / или вы хотите понять причину исходной ошибки (включая определение того, какие входные байты вызвали проблему) и выполнить преобразования кодирования по требованию, читайте далее.
Проблема в том, что кодировка входного файла не совпадает с кодировкой оболочки.
В частности, входной файл содержит символы, закодированные таким образом, который недопустим в UTF-8 (как @Klas Lindbäck заявил в комментарии) - вот что sedпытается сказать сообщение об ошибке invalid byte sequence.
Скорее всего, ваш входной файл использует однобайтовую 8-битную кодировку, например ISO-8859-1, часто используемую для кодирования "западноевропейских" языков.
Пример:
Буква с акцентом àимеет код Unicode 0xE0(224) - такой же, как и в ISO-8859-1. Однако из - за характера UTF-8 кодировке, этот единственный элемент кода представлен в виде 2 -х байт - 0xC3 0xA0, в то время как пытается передать один байт 0xE0 является недействительным в соответствии с UTF-8.
Вот демонстрация проблемы с использованием строки, voilàзакодированной как ISO-8859-1, с àпредставленным в виде одного байта (через строку bash в кавычках ANSI-C ( $'...'), которая используется \x{e0}для создания байта):
Обратите внимание, что эта sedкоманда по сути является no-op, которая просто пропускает ввод, но она нам нужна, чтобы вызвать ошибку:
# -> 'illegal byte sequence': byte 0xE0 is not a valid char.
sed 's/.*/&/' <<<$'voil\x{e0}'
Чтобы просто игнорировать проблему , LCTYPE=Cможно использовать вышеуказанный подход:
# No error, bytes are passed through ('á' will render as '?', though).
LC_CTYPE=C sed 's/.*/&/' <<<$'voil\x{e0}'
Если вы хотите определить, какие части ввода вызывают проблему , попробуйте следующее:
# Convert bytes in the 8-bit range (high bit set) to hex. representation.
# -> 'voil\x{e0}'
iconv -f ASCII --byte-subst='\x{%02x}' <<<$'voil\x{e0}'
Вывод покажет вам все байты с установленным старшим битом (байты, которые превышают 7-битный диапазон ASCII) в шестнадцатеричной форме. (Тем не менее, обратите внимание, что это также включает в себя правильно закодированные многобайтовые последовательности UTF-8 - для более точной идентификации байтов invalid-in-UTF-8 потребуется более сложный подход.)
Выполнение кодирования преобразований по требованию :
Стандартная утилита iconvможет использоваться для преобразования в ( -t) и / или из ( -f) кодировок; iconv -lперечисляет все поддерживаемые.
Примеры:
Преобразование FROM ISO-8859-1в действующую кодировку в оболочке (на основе LC_CTYPE, которая UTF-8по умолчанию -base), основываясь на приведенном выше примере:
# Converts to UTF-8; output renders correctly as 'voilà'
sed 's/.*/&/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')"
Обратите внимание, что это преобразование позволяет вам правильно сопоставлять иностранные символы :
# Correctly matches 'à' and replaces it with 'ü': -> 'voilü'
sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')"
Чтобы преобразовать ввод BACK ISO-8859-1после обработки, просто передайте результат в другую iconvкоманду:
sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voil\x{e0}')" | iconv -t ISO-8859-1