Sed re error illegal byte sequence

Ошибка RE: недопустимая последовательность байтов в Mac OS X Я пытаюсь заменить строку в Makefile в Mac OS X для кросс-компиляции в iOS. Строка содержит встроенные двойные кавычки. Команда: Я пытался избежать двойных кавычек, запятых, тире и двоеточий без радости. Например: У меня чертовски время отладить проблему. Кто-нибудь знает, как получить sed для печати […]

Содержание

  1. Ошибка RE: недопустимая последовательность байтов в Mac OS X
  2. 4 ответа
  3. Ошибка RE: незаконная последовательность байтов в Mac OS X
  4. ОТВЕТЫ
  5. Ответ 1
  6. Ответ 2
  7. Ответ 3
  8. Ответ 4
  9. Ответ 5
  10. Ответ 6
  11. Ответ 7
  12. find and sed (find and replace) causes illegal byte sequence on Mac OS X
  13. 1 Answer 1
  14. Получение «sed error — незаконная последовательность байтов» (в bash)
  15. ОТВЕТЫ
  16. Ответ 1
  17. Ответ 2
  18. Ответ 3
  19. Ответ 4

Ошибка RE: недопустимая последовательность байтов в Mac OS X

Я пытаюсь заменить строку в Makefile в Mac OS X для кросс-компиляции в iOS. Строка содержит встроенные двойные кавычки. Команда:

Я пытался избежать двойных кавычек, запятых, тире и двоеточий без радости. Например:

У меня чертовски время отладить проблему. Кто-нибудь знает, как получить sed для печати позиции незаконной последовательности байтов? Или кто-нибудь знает, что такое незаконная последовательность байтов?

4 ответа

Пример команды, которая проявляет симптом: sed ‘s/./@/’ : это не удается, потому что байт 0xfc не является допустимым UTF-8 char.
Обратите внимание, что GNU sed (Linux, но также устанавливаемый на macOS), напротив, просто пропускает недопустимый байт, не сообщая об ошибке.

Использование ранее принятого ответа является вариантом, если вы не возражаете против поддержки вашей истинной локали (если вы находитесь на американской системы, и вам никогда не придется иметь дело с иностранными персонажами, это может быть хорошо.)

Однако тот же эффект может иметь ad-hoc только для одной команды:

Примечание. Важно, чтобы эффективная установка 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 (как указано в комментарии KKK 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 , с à , представленной как один байт (через строку с символом ANSI-C bash $’. ‘ ), который использует x для создания байта):

Обратите внимание, что команда sed фактически является no-op, которая просто передает вход через, но нам нужно это, чтобы спровоцировать ошибку:

Чтобы просто игнорировать проблему, можно использовать описанный выше подход LCTYPE=C :

Если вы хотите определить, какие части ввода вызывают проблема, попробуйте следующее:

На выходе будут показаны все байты с высоким набором бит (байты, которые превышают 7-разрядный диапазон ASCII) в шестнадцатеричной форме. (Обратите внимание, однако, что это также включает правильно кодированные многобайтовые последовательности UTF-8 — для более точного определения байтов с недействительными в UTF-8 потребуется более сложный подход).

Выполнение конверсий по требованию:

Стандартная утилита iconv может использоваться для преобразования в ( -t ) и/или из ( -f ) кодировок; iconv -l перечислены все поддерживаемые.

Преобразуйте FROM ISO-8859-1 в кодировку, действующую в оболочке (на основе LC_CTYPE , которая по умолчанию основана на UTF-8 ), основываясь на приведенном выше примере:

Обратите внимание, что это преобразование позволяет правильно сопоставить иностранные символы:

Чтобы преобразовать входной BACK в ISO-8859-1 после обработки, просто передайте результат другой команде iconv :

Источник

Ошибка RE: незаконная последовательность байтов в Mac OS X

Я пытаюсь заменить строку в Makefile в Mac OS X для кросс-компиляции в iOS. Строка содержит встроенные двойные кавычки. Команда:

Я пытался избежать двойных кавычек, запятых, тире и двоеточий без радости. Например:

У меня чертовски время отладить проблему. Кто-нибудь знает, как получить sed для печати позиции незаконной последовательности байтов? Или кто-нибудь знает, что такое незаконная последовательность байтов?

ОТВЕТЫ

Ответ 1

Пример команды с симптомом: sed ‘s/./@/’ завершается неудачно, поскольку байт 0xfc не является допустимым 0xfc UTF-8.
Обратите внимание, что, напротив, GNU sed (Linux, но также устанавливается на macOS) просто пропускает недействительный байт, не сообщая об ошибке.

Использование ранее принятого ответа — вариант, если вы не против потерять поддержку своего истинного языка (если вы работаете в системе США и вам никогда не нужно иметь дело с иностранными символами, это может быть хорошо).

Тем не менее, тот же эффект может иметь место ad-hoc только для одной команды:

Примечание: важна эффективная настройка LC_CTYPE для C , поэтому LC_CTYPE=C sed. обычно также будет работать, но если для LC_ALL будет установлено значение (отличное от C ), он будет переопределять отдельные LC_* -category такие как LC_CTYPE . Таким образом, самый надежный подход — установить LC_ALL .

Однако (эффективно) установка LC_CTYPE в C обрабатывает строки так, как если бы каждый байт был своим собственным символом (не выполняется интерпретация на основе правил кодирования), без учета кодирования UTF-8 — multibyte-on-demand — которое использует OS X по умолчанию, где иностранные символы имеют многобайтовые кодировки.

В двух словах: установка LC_CTYPE в C заставляет оболочку и утилиты распознавать только основные английские буквы как буквы (те, которые находятся в 7-битном диапазоне ASCII), так что внешние символы. не будут рассматриваться как буквы, что приведет, например, к неудачным преобразованиям upper-/строчными буквами.

Опять же, это может быть хорошо, если вам не нужно сопоставлять многобайтовые символы, такие как é , и просто хотите пропустить такие символы.

Если этого недостаточно и/или вы хотите понять причину исходной ошибки (включая определение того, какие входные байты вызвали проблему) и выполнить преобразования кодирования по требованию, читайте ниже.

Проблема в том, что кодировка входного файла не соответствует оболочке.
Более конкретно, входной файл содержит символы, закодированные таким образом, который недопустим в UTF-8 (как @Klas Lindbäck заявил в комментарии) — это то, что пытается сказать сообщение об ошибке sed с помощью invalid byte sequence .

Скорее всего, ваш входной файл использует однобайтовую 8-битную кодировку, такую как ISO-8859-1 , часто используемую для кодирования «западноевропейских» языков.

Пример:

Буква с акцентом à имеет кодовую 0xE0 Unicode 0xE0 (224) — так же, как в ISO-8859-1 . Однако из-за характера кодирования UTF-8 эта единственная 0xC3 0xA0 представлена в виде 2 байтов — 0xC3 0xA0 , тогда как попытка передать один байт 0xE0 недопустима в UTF-8.

Здесь демонстрация проблемы с использованием строки voilà закодированной как ISO-8859-1 , с à представленной одним байтом (через строку bash в кавычках ANSI-C ( $’. ‘ ), которая использует x создать байт):

Обратите внимание на то, что команда sed по сути является no-op, которая просто пропускает ввод, но она нам нужна, чтобы вызвать ошибку:

Чтобы просто проигнорировать проблему, можно использовать вышеуказанный LCTYPE=C :

Если вы хотите определить, какие части ввода вызывают проблему, попробуйте следующее:

Вывод покажет вам все байты с установленным старшим битом (байты, которые превышают 7-битный диапазон ASCII) в шестнадцатеричной форме. (Тем не менее, обратите внимание, что это также включает в себя правильно закодированные многобайтовые последовательности UTF-8 — потребуется более сложный подход для конкретной идентификации байтов invalid-in-UTF-8.)

Выполнение кодирования преобразований по требованию:

Стандартная утилита iconv может использоваться для преобразования в ( -t ) и/или из ( -f ) кодировок; iconv -l перечисляет все поддерживаемые.

Примеры:

Преобразование из ISO-8859-1 в действующую кодировку в оболочке (на основе LC_CTYPE , по умолчанию UTF-8 -based), основываясь на приведенном выше примере:

Обратите внимание, что это преобразование позволяет вам правильно сопоставлять иностранные символы:

Чтобы преобразовать ввод BACK в ISO-8859-1 после обработки, просто передайте результат в другую команду iconv :

Ответ 2

Добавьте следующие строки в

Ответ 3

mklement0 answer отлично, но у меня есть небольшие настройки.

Кажется хорошей идеей явно указать bash кодировку при использовании iconv . Кроме того, мы должны добавить знак байтового байта (хотя стандарт unicode не рекомендует его), потому что может быть законные путаницы между UTF-8 и ASCII без знака байтового порядка. К сожалению, iconv не добавляет знак байтового байта, когда вы явно указываете endianness ( UTF-16BE или UTF-16LE ), поэтому нам нужно использовать UTF-16 , который использует специфичность для платформы, а затем используйте file —mime-encoding , чтобы обнаружить истинную сущность iconv .

(Я задерживаю все свои кодировки, потому что, когда вы перечисляете все поддерживаемые iconv кодировки с помощью iconv -l , они все в верхнем регистре.)

Ответ 4

Мой обходной путь использовал Perl:

Ответ 5

Вы просто должны передать команду iconv перед командой sed. Например, с вводом file.txt:

iconv -f ISO-8859-1 -t UTF8-MAC file.txt | Sed ‘s/что-то/àéèêçùû /g’ |.

Опция -f — это набор кодов «из», а опция -t — это преобразование кодового набора «в».

Позаботьтесь о том, чтобы веб-страницы обычно отображались в нижнем регистре, например , а iconv использует верхний регистр. В вашей системе есть список поддерживаемых наборов кодов iconv с помощью команды iconv -l

UTF8-MAC — это современный OS Mac кодовый набор для конвертации.

Ответ 6

В моем обходном пути использовался gnu sed . Работал хорошо для моих целей.

Ответ 7

Просто используйте каналы из внешней системы в macOS

или во внешнюю систему из macOS

UTF8-MAC — стандартная современная кодировка macOS

ISO-8859-1 — западная западная кодировка

список кодировок командной строки в вашей системе с

Источник

find and sed (find and replace) causes illegal byte sequence on Mac OS X

I am attempting to perform a find and replace of underscores to dots in a directory for certain filetypes only (.mkv, .mp4, .avi). This is the code that I am using (I’m on Mac OS X 10.9):

I read up on two solutions, both which have not worked.

I first I added the following to my

This caused the same error, so then I tried using:

and this did not work, I received this error:

Any other suggestions? I’m quite new to shell.

EDIT: This is what I am trying to accomplish:

I am trying to go through a directory and replace the underscores in the file names to dots.

random_movie.mp4 should be random.movie.mp4

1 Answer 1

You should be using -exec here:

As written this only prints the command it will execute if you go through with it. For example, running the above on my . /media/Videos directory prints some of the following:

In order to go through with it you’d need to change:

In general you should avoid passing filenames and similar over a pipe because when you do so you lose the the delimiters to the head and tail of the filename — it ceases to be an argument and becomes instead a sequence of bytes in a stream. The -exec option to find enables you to retain those delimiters in a child process of the running find process. With + it acts like xargs — execing the specified child process only as often as necessary to avoid an ARGMAX condition.

Regarding the sed problem — you might try:

That should at least avoid xargs interpreting the environment variable declaration as an argument. It will not help you to edit any filenames, though.

A last note — the issue you mention is generally caused by an incomplete multi-byte sequence occurring in pattern space. POSIX specifies that . cannot match part of a character — and so .* loses its meaning in that context. Forcing the C locale should resolve it — but another option for clearing hold/pattern spaces with a GNU sed is the z command.

Источник

Получение «sed error — незаконная последовательность байтов» (в bash)

Выполнение редактирования потока, чтобы изменить неприятный значок Parallels. Он плохо развит и встроен в приложение, а не является файлом изображения. Поэтому я нашел эту команду sed, которая имеет хорошие отзывы:

Он возвращает sed: RE error: illegal byte sequence

Может кто-нибудь объяснить, что это значит? Какая часть команды является проблемой?

ОТВЕТЫ

Ответ 1

Попробуйте установить переменную среды LANG ( LANG=C sed . ) или используйте один из двоичных инструментов sed, упомянутых здесь: двоичная замена sed

Почему ошибка?

Без LANG=C sed предполагает, что файлы закодированы в любом кодировании, указанном в LANG , и файл (будучи двоичным) может содержать байты, которые не являются допустимыми символами в кодировке LANG (таким образом, вы можете получить «незаконный байт» последовательность ‘).

Почему работает LANG=C ?

C просто происходит, чтобы обрабатывать все символы ASCII как себя, а не символы ASCII как литералы.

Ответ 2

LANG=C один не помогло, но добавил LC_CTYPE=C , а также решил его.

Ответ 3

Мне удалось это сделать, запустив:

перед командой sed .

Не уверен, что я сделал или почему он работает, но это произошло.

Ответ 4

В дополнение к LANG=C и LC_CTYPE=C мне пришлось сделать LC_ALL=C , чтобы заставить это работать.

LC_ALL переопределяет все отдельные категории LC_* . Таким образом, наиболее надежным подходом является использование LC_ALL=C sed . — не нужно также обращаться с другими переменными.

Источник

You should be using -exec here:

find . ( -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' ) 
    -exec sh -cf 'IFS=._
    for f do d=${f%/*} f=${f##*/}
    [ -n "${f##*_*}" ] && continue
    set -- $f 
    printf "%sn" "mv \" "$d/$f \" "$d/$*"
    done' find.rename.shc {} +

As written this only prints the command it will execute if you go through with it. For example, running the above on my .../media/Videos directory prints some of the following:

mv 
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure_Time.s05e37.The_Box_Prince.mp4 
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure.Time.s05e37.The.Box.Prince.mp4
mv 
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure_Time.s05e38.Red_Starved.mp4 
/mnt/bcache/media/Videos/TV/Adventure_Time/Adventure.Time.s05e38.Red.Starved.mp4

In order to go through with it you’d need to change:

...
set -- $f
printf "%sn" "mv \" "$d/$f \" "$d/$*"
...

…to just…

...
set -- $f; mv "$d/$f" "$d/$*"
...

In general you should avoid passing filenames and similar over a pipe because when you do so you lose the the delimiters to the head and tail of the filename — it ceases to be an argument and becomes instead a sequence of bytes in a stream. The -exec option to find enables you to retain those delimiters in a child process of the running find process. With + it acts like xargs — execing the specified child process only as often as necessary to avoid an ARGMAX condition.

Regarding the sed problem — you might try:

LC_ALL=C xargs sed ...

That should at least avoid xargs interpreting the environment variable declaration as an argument. It will not help you to edit any filenames, though.

A last note — the issue you mention is generally caused by an incomplete multi-byte sequence occurring in pattern space. POSIX specifies that . cannot match part of a character — and so .* loses its meaning in that context. Forcing the C locale should resolve it — but another option for clearing hold/pattern spaces with a GNU sed is the z command.

With a UTF-8 locale, this sed command to insert a character at the beginning of each line incorrectly crashes with an error about an illegal byte sequence:

$ echo “hi | LANG=en_US.UTF-8 sed -e s'/^/x/g'
sed: RE error: illegal byte sequence

If you change the ^ to an ordinary character, or drop the g flag, it works fine. I’m guessing the g makes it check the line again, but it gets messed up trying to find the start of the line with the multi-byte character there.

I’m seeing this on both Ventura on arm and Monterey on intel, and haven’t checked further back than that. I know that the sed is BSD-derived, so I did test this on FreeBSD 13.1 and it does not have this bug.

I’ve never filed a bug with Apple before. If I file this as a bug with Feedback Assistant, what on earth do I tag it with in the hopes that the apple sed maintainer(s) might see it? There’s no ‘sed’ or ‘unix’ or ‘command line tools’ option.

Replies

Are you sure? You’re using a non-standard double-quote before hi.

When you use this, it works fine:

Command: echo "hi" | LANG=en_US.UTF-8 sed -e s'/^/x/g'

Output: xhi

Yeah, I know that’s a multi-byte quote character. The bug is with multi-byte characters at the start of a line. Try:

$ echo ø | LANG=en_US.UTF-8 sed -e 's/^/o/g'
sed: RE error: illegal byte sequence

Sed processes the same character correctly in other very similar regexes:

$ echo ø | LANG=en_US.UTF-8 sed -e 's/ø/o/g'
o

Oh, I get you now. Yes, but doesn’t that suggest that the characters you’re using aren’t UTF-8? For example, this works:

Command: echo ø | LANG=ISO-8859-1 sed -e 's/^/o/g'

Output:

Yes, the input is definitely UTF-8. You can double-check the “UTF-8 (hex)” line of https://www.fileformat.info/info/unicode/char/00f8/index.htm

$ echo ø > foo
$ hexdump -C foo
00000000  c3 b8 0a                                          |...|
00000003
$ LANG=en_US.UTF-8 sed -e 's/^/o/g' < foo
sed: RE error: illegal byte sequence
Returned 1.
# Almost everyone’s terminal is going to be UTF-8 anyway; I only included $LANG to be explicit
$ sed -e 's/^/o/g' < foo
sed: RE error: illegal byte sequence
Returned 1.

ISO-8859-1 isn’t a multi-byte encoding. If you want to convert a UTF-8 character to it, echo ø | iconv -f UTF-8 -t ISO-8859-1 will do it but then you’ll also need to supply the sed regex in the correct encoding and you still won’t be able to trigger this bug that way because it is a bug in sed’s handling of multibyte characters.

Hi, I appreciate you trying to help, but setting LC_CTYPE=C won’t work
for me. The text I’m processing is UTF-8 encoded, and definitely contains
non-ascii characters. If sed isn’t provided the correct encoding, that
breaks pretty basic regular expressions like, ‘find all the three-letter
words.’

    $ (echo foo; echo bar; echo føo) | sed -e 's/^...$/three-letter-word/g'
    three-letter-word
    three-letter-word
    three-letter-word
    $ (echo foo; echo bar; echo føo) | LC_CTYPE=C sed -e 's/^...$/three-letter-word/g'
    three-letter-word
    three-letter-word
    føo

Now there is an edge case here, where that regular expression won’t work as
expected if there are combining characters in the input, perhaps from an
unexpected unicode normalization format, but that’s more advanced than I
need right now.

Some relevant links:

  • https://crashcourse.housegordon.org/coreutils-multibyte-support.html#useful-websites
  • https://ftfy.vercel.app

Since GNU sed and FreeBSD sed handle s/^/x/g properly on inputs starting
with multi-byte characters, I’m certain this is a bug in macOS
sed.

If anyone has guidance for categorizing tickets for unix command-line tools
in Feedback Assistant, that would be great.

As you said, gnu-sed handles it correctly, so can’t you just use that?

brew install gsed

echo ø | LANG=en_US.UTF-8 gsed -e 's/^/o/g'

Output:

echo “hi | LANG=en_US.UTF-8 gsed -e s'/^/x/g'

Output: x“hi

darkpaw wrote:

so can’t you just use that?

Sure, but it’d be nice to get a bug on file about this as well.


andrew_n wrote:

If anyone has guidance for categorizing tickets for unix command-line
tools in Feedback Assistant, that would be great.

At the first page, choose macOS. In the “Which area are you seeing an issue with?” popup, choose “Something else not on this list”.

For more bug reporting hints and tips, see Bug Reporting: How and Why?
.

And please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

The g character in 's/^/o/g' means «replace each occurrence in the current line». Otherwise it would replace only the first occurrence of each line.

In the particular case where the regexp begins with the caret ^, which means «the regexp should match the beginning of the line», it makes no sense to use the g option.

On my mac, I get the following:

% echo 'ønø' | sed -e 's/^/o/g'
sed: RE error: illegal byte sequence

% echo 'ønø' | sed -e 's/^/o/' 
oø
oø

Я пытаюсь заменить строку в Makefile в Mac OS X для кросс-компиляции в iOS. Строка содержит встроенные двойные кавычки. Команда:

sed -i "" 's|"iphoneos-cross","llvm-gcc:-O3|"iphoneos-cross","clang:-Os|g' Configure

И ошибка:

sed: RE error: illegal byte sequence

Я пытался избежать двойных кавычек, запятых, тире и двоеточий без радости. Например:

sed -i "" 's|"iphoneos-cross","llvm-gcc:-O3|"iphoneos-cross","clang:-Os|g' Configure

У меня чертовски время отладить проблему. Кто-нибудь знает, как получить sed для печати позиции незаконной последовательности байтов? Или кто-нибудь знает, что такое незаконная последовательность байтов?

4b9b3361

Ответ 1

Пример команды с симптомом: sed 's/./@/' <<<$'xfc' завершается неудачно, поскольку байт 0xfc не является допустимым 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_* -category такие как LC_CTYPE. Таким образом, самый надежный подход — установить LC_ALL.

Однако (эффективно) установка LC_CTYPE в C обрабатывает строки так, как если бы каждый байт был своим собственным символом (не выполняется интерпретация на основе правил кодирования), без учета кодирования UTF-8 — multibyte-on-demand — которое использует OS X по умолчанию, где иностранные символы имеют многобайтовые кодировки.

В двух словах: установка LC_CTYPE в C заставляет оболочку и утилиты распознавать только основные английские буквы как буквы (те, которые находятся в 7-битном диапазоне ASCII), так что внешние символы. не будут рассматриваться как буквы, что приведет, например, к неудачным преобразованиям upper-/строчными буквами.

Опять же, это может быть хорошо, если вам не нужно сопоставлять многобайтовые символы, такие как é, и просто хотите пропустить такие символы.

Если этого недостаточно и/или вы хотите понять причину исходной ошибки (включая определение того, какие входные байты вызвали проблему) и выполнить преобразования кодирования по требованию, читайте ниже.


Проблема в том, что кодировка входного файла не соответствует оболочке.
Более конкретно, входной файл содержит символы, закодированные таким образом, который недопустим в UTF-8 (как @Klas Lindbäck заявил в комментарии) — это то, что пытается сказать сообщение об ошибке sed с помощью invalid byte sequence.

Скорее всего, ваш входной файл использует однобайтовую 8-битную кодировку, такую как ISO-8859-1, часто используемую для кодирования «западноевропейских» языков.

Пример:

Буква с акцентом à имеет кодовую 0xE0 Unicode 0xE0 (224) — так же, как в ISO-8859-1. Однако из-за характера кодирования UTF-8 эта единственная 0xC3 0xA0 представлена в виде 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/.*/&/' <<<$'voilx{e0}'

Чтобы просто проигнорировать проблему, можно использовать вышеуказанный LCTYPE=C:

  # No error, bytes are passed through ('á' will render as '?', though).
LC_CTYPE=C sed 's/.*/&/' <<<$'voilx{e0}'

Если вы хотите определить, какие части ввода вызывают проблему, попробуйте следующее:

  # Convert bytes in the 8-bit range (high bit set) to hex. representation.
  # -> 'voilx{e0}'
iconv -f ASCII --byte-subst='x{%02x}' <<<$'voilx{e0}'

Вывод покажет вам все байты с установленным старшим битом (байты, которые превышают 7-битный диапазон ASCII) в шестнадцатеричной форме. (Тем не менее, обратите внимание, что это также включает в себя правильно закодированные многобайтовые последовательности UTF-8 — потребуется более сложный подход для конкретной идентификации байтов invalid-in-UTF-8.)


Выполнение кодирования преобразований по требованию:

Стандартная утилита iconv может использоваться для преобразования в (-t) и/или из (-f) кодировок; iconv -l перечисляет все поддерживаемые.

Примеры:

Преобразование из ISO-8859-1 в действующую кодировку в оболочке (на основе LC_CTYPE, по умолчанию UTF-8 -based), основываясь на приведенном выше примере:

  # Converts to UTF-8; output renders correctly as 'voilà'
sed 's/.*/&/' <<<"$(iconv -f ISO-8859-1 <<<$'voilx{e0}')"

Обратите внимание, что это преобразование позволяет вам правильно сопоставлять иностранные символы:

  # Correctly matches 'à' and replaces it with 'ü': -> 'voilü'
sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voilx{e0}')"

Чтобы преобразовать ввод BACK в ISO-8859-1 после обработки, просто передайте результат в другую команду iconv:

sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voilx{e0}')" | iconv -t ISO-8859-1

Ответ 2

Добавьте следующие строки в ~/.bash_profile или ~/.zshrc файл (ы).

export LC_CTYPE=C 
export LANG=C

Ответ 3

mklement0 answer отлично, но у меня есть небольшие настройки.

Кажется хорошей идеей явно указать bash кодировку при использовании iconv. Кроме того, мы должны добавить знак байтового байта (хотя стандарт unicode не рекомендует его), потому что может быть законные путаницы между UTF-8 и ASCII без знака байтового порядка. К сожалению, iconv не добавляет знак байтового байта, когда вы явно указываете endianness (UTF-16BE или UTF-16LE), поэтому нам нужно использовать UTF-16, который использует специфичность для платформы, а затем используйте file --mime-encoding, чтобы обнаружить истинную сущность iconv.

(Я задерживаю все свои кодировки, потому что, когда вы перечисляете все поддерживаемые iconv кодировки с помощью iconv -l, они все в верхнем регистре.)

# Find out MY_FILE encoding
# We'll convert back to this at the end
FILE_ENCODING="$( file --brief --mime-encoding MY_FILE )"
# Find out bash encoding, with which we should encode
# MY_FILE so sed doesn't fail with 
# sed: RE error: illegal byte sequence
BASH_ENCODING="$( locale charmap | tr [:lower:] [:upper:] )"
# Convert to UTF-16 (unknown endianness) so iconv ensures
# we have a byte-order mark
iconv -f "$FILE_ENCODING" -t UTF-16 MY_FILE > MY_FILE.utf16_encoding
# Whether we're using UTF-16BE or UTF-16LE
UTF16_ENCODING="$( file --brief --mime-encoding MY_FILE.utf16_encoding )"
# Now we can use MY_FILE.bash_encoding with sed
iconv -f "$UTF16_ENCODING" -t "$BASH_ENCODING" MY_FILE.utf16_encoding > MY_FILE.bash_encoding
# sed!
sed 's/.*/&/' MY_FILE.bash_encoding > MY_FILE_SEDDED.bash_encoding
# now convert MY_FILE_SEDDED.bash_encoding back to its original encoding
iconv -f "$BASH_ENCODING" -t "$FILE_ENCODING" MY_FILE_SEDDED.bash_encoding > MY_FILE_SEDDED
# Now MY_FILE_SEDDED has been processed by sed, and is in the same encoding as MY_FILE

Ответ 4

Мой обходной путь использовал Perl:

find . -type f -print0 | xargs -0 perl -pi -e 's/was/now/g'

Ответ 5

Вы просто должны передать команду iconv перед командой sed. Например, с вводом file.txt:

iconv -f ISO-8859-1 -t UTF8-MAC file.txt | Sed ‘s/что-то/àéèêçùû /g’ |…

Опция -f — это набор кодов «из», а опция -t — это преобразование кодового набора «в».

Позаботьтесь о том, чтобы веб-страницы обычно отображались в нижнем регистре, например <charset = iso-8859-1 «/>, а iconv использует верхний регистр. В вашей системе есть список поддерживаемых наборов кодов iconv с помощью команды iconv -l

UTF8-MAC — это современный OS Mac кодовый набор для конвертации.

Ответ 6

В моем обходном пути использовался gnu sed. Работал хорошо для моих целей.

Ответ 7

Просто используйте каналы из внешней системы в macOS

... | iconv  -f ISO-8859-1 -t UTF8-MAC | sed 's/a/A/g'|....

или во внешнюю систему из macOS

... | sed 's/a/A/g'| iconv  -f UTF8-MAC t- ISO-8859-1 |....

В этом примере

UTF8-MAC — стандартная современная кодировка macOS

ISO-8859-1 — западная западная кодировка

список кодировок командной строки в вашей системе с

iconv -l

Пример команды, демонстрирующей симптом: sed 's/./@/' <<<$'xfc' терпит неудачу, потому что байт 0xfc не является допустимым символом UTF-8.
Обратите внимание, что, напротив, GNU sed (Linux, но также можно установить на macOS) просто пропускает недопустимый байт, не сообщая об ошибке.

Посмотрите на график ранее принятый ответ это вариант, если вы не возражаете против потери поддержки вашей истинной локали (если вы работаете в системе США и вам никогда не приходится иметь дело с иностранными символами, это может быть хорошо.)

Однако такой же эффект может быть специальной для единственная команда только:

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 is недействительный под UTF-8.

Вот демонстрация проблемы используя строку voilà закодировано как ISO-8859-1, С à представленный как one байт (через строку bash в кавычках ANSI-C ($'...') который использует x{e0} для создания байта):

Обратите внимание, что sed Команда фактически является пустой операцией, которая просто пропускает ввод, но нам нужно, чтобы она спровоцировала ошибку:

  # -> 'illegal byte sequence': byte 0xE0 is not a valid char.
sed 's/.*/&/' <<<$'voilx{e0}'

Чтобы просто игнорировать проблема, над LCTYPE=C можно использовать подход:

  # No error, bytes are passed through ('á' will render as '?', though).
LC_CTYPE=C sed 's/.*/&/' <<<$'voilx{e0}'

Если ты хочешь определить, какие части ввода вызывают проблемупопробуйте следующее:

  # Convert bytes in the 8-bit range (high bit set) to hex. representation.
  # -> 'voilx{e0}'
iconv -f ASCII --byte-subst='x{%02x}' <<<$'voilx{e0}'

Вывод покажет вам все байты, для которых установлен старший бит (байты, которые превышают 7-битный диапазон ASCII) в шестнадцатеричной форме. (Обратите внимание, однако, что это также включает в себя правильно закодированные многобайтовые последовательности UTF-8 — потребуется более сложный подход для конкретной идентификации недопустимых байтов в UTF-8.)


Выполнение преобразований кодирования по запросу:

Стандартная утилита iconv можно использовать для преобразования в (-t) и/или из (-f) кодировки; iconv -l перечисляет все поддерживаемые.

Примеры:

Конвертировать ИЗ ISO-8859-1 к кодировке, действующей в оболочке (на основе LC_CTYPE, Которая является UTF-8-based по умолчанию), основанный на приведенном выше примере:

  # Converts to UTF-8; output renders correctly as 'voilà'
sed 's/.*/&/' <<<"$(iconv -f ISO-8859-1 <<<$'voilx{e0}')"

Обратите внимание, что это преобразование позволяет правильно сопоставлять иностранные символы:

  # Correctly matches 'à' and replaces it with 'ü': -> 'voilü'
sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voilx{e0}')"

Чтобы преобразовать ввод BACK в ISO-8859-1 после обработки просто передать результат другому iconv команда:

sed 's/à/ü/' <<<"$(iconv -f ISO-8859-1 <<<$'voilx{e0}')" | iconv -t ISO-8859-1

Понравилась статья? Поделить с друзьями:
  • Securom reported error 2000 gta 4 fix
  • Security violation error detected
  • Security spp ошибка 16385
  • Security spp 8233 ошибка как исправить
  • Security spp 8198 ошибка как исправить