Я недавно вошел в использование инструментов как 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, после которого это хорошо работало!
Это - типичная проблема кодирования символа. .
средства любой символ. Но то, какая последовательность байта является допустимым символом, является вопросом кодирования. Контакт с текстом без ведома кодирования является верным отказом. Ваша команда 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 ...