grep regex.* не соответствие всему

Я недавно вошел в использование инструментов как grep, wc, cat, и т.д., потому что я должен иметь дело с некоторыми очень большими файлами CSV (> 10 ГБ), которые не вполне разграничены правильно (например, имея случаи символа-разделителя в некоторых полях.

В моей работе с одним из этих файлов я выполнил следующую команду в процессе попытки выяснить способ правильно определить который экземпляры ; разделитель, и замените их некоторым другим символом:

grep -v -n --text "[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9].*[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9].*[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9].*[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]" < Transactions.csv

regex может, вероятно, быть сделан намного лучше, но так или иначе; то, что удивительно, - то, что среди других вышеупомянутый код производит следующую строку:

12345678:2016-10-25;12345678912345;2016-10-25;gobbledegook �IDNR: 69 ;12345.67;.00;2003-09-05;12345678;2003-09-03;stuff stuff         ;12345 fgadfkjgbsdkb;12/3/45678/9

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

Я подозреваю, что файл сохранен с помощью кодировки UTF-16, если это имеет какое-либо значение.

Править: Благодаря @exore для ответа. Как оказалось, мой файл был закодирован в ISO-8859-15, которым я смог фигурировать grepпроверьте с помощью ping-запросов строки, содержащие специальные символы, которые были относительно немногими в файл и открытие это в gedit. Я затем использовал iconv преобразовать это в utf8, после которого это хорошо работало!

1
задан 16 November 2016 в 14:22

1 ответ

Это - типичная проблема кодирования символа. . средства любой символ. Но то, какая последовательность байта является допустимым символом, является вопросом кодирования. Контакт с текстом без ведома кодирования является верным отказом. Ваша команда grep, вероятно, ожидает UTF-8 закодированная строка. UTF-8 является многобайтовым кодированием, означая, что некоторый символ представлен несколькими байтами. Однако не вся последовательность байтов допустимы. Посмотрите, например, статья Wikipedia о UTF-8.

, Когда grep встречается с последовательностью байта, которая не является допустимым символом в ожидаемом кодировании, это не может распознать его как символ, строка не соответствует, это производится. Так как Ваш терминал не распознает символ также, Вы добираетесь .

в Вашем случае существует обходное решение. Скажите grep не беспокоиться о кодировании и рассматривать один байт как один символ.

env LANG=C grep ....

или возможно

env LANG=C LC_ALL=C grep ....

можно протестировать легко:

Создают 2 файла, один закодированный utf-8, один utf-16-be:

$ echo éléphant | tee file.std | iconv -f utf8 -t utf16be >file.utf16be

контент Проверки файлов:

$ cat file*
éléphant
�l�phant

Попытка к grep. Строка utf16be не распознана, никакой вывод:

$ grep '^.* 

не используют кодирование вообще. Один байт является одним символом. все строки подобраны, пїЅ просто означает, что терминал не распознает последовательность utf16be как допустимый utf-8 символ. Отметьте использование -a, чтобы сказать grep полагать, что двоичный файл, некоторый текст.

$ env LANG=C grep -a '^.* 

, С другой стороны, если Вы знаете кодирование, затем можно использовать iconv для первого преобразования файла, затем используют grep. Одно из следующего должно работать.

iconv -f utf16   -t utf8 < file | grep ...
iconv -f utf16le -t utf8 < file | grep ...
iconv -f utf16be -t utf8 < file | grep ...
file* file.std:éléphant file.utf16be:�l�phant

, С другой стороны, если Вы знаете кодирование, затем можно использовать iconv для первого преобразования файла, затем используют grep. Одно из следующего должно работать.

iconv -f utf16   -t utf8 < file | grep ...
iconv -f utf16le -t utf8 < file | grep ...
iconv -f utf16be -t utf8 < file | grep ...
file* file.std:éléphant

не используют кодирование вообще. Один байт является одним символом. все строки подобраны, пїЅ просто означает, что терминал не распознает последовательность utf16be как допустимый utf-8 символ. Отметьте использование -a, чтобы сказать grep полагать, что двоичный файл, некоторый текст.

$ env LANG=C grep -a '^.* 

, С другой стороны, если Вы знаете кодирование, затем можно использовать iconv для первого преобразования файла, затем используют grep. Одно из следующего должно работать.

iconv -f utf16   -t utf8 < file | grep ...
iconv -f utf16le -t utf8 < file | grep ...
iconv -f utf16be -t utf8 < file | grep ...
file* file.std:éléphant file.utf16be:�l�phant

, С другой стороны, если Вы знаете кодирование, затем можно использовать iconv для первого преобразования файла, затем используют grep. Одно из следующего должно работать.

iconv -f utf16   -t utf8 < file | grep ...
iconv -f utf16le -t utf8 < file | grep ...
iconv -f utf16be -t utf8 < file | grep ...
1
ответ дан 7 December 2019 в 15:44

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

Похожие вопросы: