#linux #bash
У меня есть большой файл (около 30 гб), мне нужно из него вырезать все строки, которые содержат, что либо кроме a-zA-Z0-9 и всех спецсимволов (!@#$%^&*() ... и т.д.).
Ответы
Ответ 1
~$ grep -Pv "^[a-zA-Z0-9!@\#\$%\^\&\*\\(\\)\\[\\]\\{\\}]*$" big_file добавте в группу что пропущенно -v игнорировать строки содержащие патерн После небольших изысканий: UCS characters U+0000 to U+007F (ASCII) are encoded simply as bytes 0x00 to 0x7F (ASCII compatibility). This means that files and strings which contain only 7-bit ASCII characters have the same encoding under both ASCII and UTF-8. у grep есть функция чтения бинарных файлов как текст. Получается нужно исключить значения от b\x00 до b\x7F ~$ grep -Pav '^[b\x00-b\x7F]*$' big_file Да интересный вопрос вышел, в лесу разнообразных кодировок для печатных символов можно заблудится. Рабочий вариант на основе ключевой статьи [4]. Просуммировав все выше перечисленное, нужно найти шестнадцатеричные последовательности удовлетворяющие условие [\x00-\x7D] но вывести все символы за пределами этого промежутка. Конечно если речь идет о чем то подобном UNICODE/UTF-8/ASCII, а не "сыром" бинарном файле. ~$ cat test-3 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]@abcdefghijklmnopqrstuvwxyz{|}| АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮюЯя ~$ hexdump -C test-3 00000000 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| 00000010 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 |123456789:;<=>?@| 00000020 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 |ABCDEFGHIJKLMNOP| 00000030 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 40 61 62 |QRSTUVWXYZ[\]@ab| 00000040 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 |cdefghijklmnopqr| 00000050 73 74 75 76 77 78 79 7a 7b 7c 7d 7c 0a d0 90 d0 |stuvwxyz{|}|....| 00000060 b0 d0 91 d0 b1 d0 92 d0 b2 d0 93 d0 b3 d0 94 d0 |................| 00000070 b4 d0 95 d0 b5 d0 81 d1 91 d0 96 d0 b6 d0 97 d0 |................| 00000080 b7 d0 98 d0 b8 d0 99 d0 b9 d0 9a d0 ba d0 9b d0 |................| 00000090 bb d0 9c d0 bc d0 9d d0 bd d0 9e d0 be d0 9f d0 |................| 000000a0 bf d0 a0 d1 80 d0 a1 d1 81 d0 a2 d1 82 d0 a3 d1 |................| 000000b0 83 d0 a4 d1 84 d0 a5 d1 85 d0 a6 d1 86 d0 a7 d1 |................| 000000c0 87 d0 a8 d1 88 d0 a9 d1 89 d0 aa d1 8a d0 ab d1 |................| 000000d0 8b d0 ac d1 8c d0 ad d1 8d d0 ae d1 8e d0 af d1 |................| 000000e0 8f 0a |..| 000000e2 ~$ LC_CTYPE=C grep -Pv "[\x00-\x7D]" test-3 АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮюЯя Т.к. вопрос не определен до конца, добавил свой критерий: вывести любую строку НЕ содержащую символ со значением от x00 до x7D. Ссылки https://stackoverflow.com/questions/3752913 https://unix.stackexchange.com/questions/19907 https://unix.stackexchange.com/questions/19491 https://stackoverflow.com/questions/31139737 Спецификация ASCII и UNICODE https://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 https://en.wikipedia.org/wiki/ASCIIОтвет 2
Спасибо за вопрос, неожиданно трудный при кажущейся простоте. Я не смог решить его при помощи grep, но простой скрипт на перле делает то что нужно: -- myfilter.pl -- while () { if ($_ !~ m/[^\w\s\/^.@#$%&*(){}\[\],:;?!<>-]/) { print "$_"; } } Использование: cat big_file.txt |perl myfilter.pl >filtered_file.txt Пустые строки сохраняются!
Комментариев нет:
Отправить комментарий