2016-03-17 5 views
2

Предположим, что мы выполняем многострочный поиск по шаблону регулярных выражений в кучке файлов, и мы хотим извлечь совпадения из grep. По умолчанию выходные значения grep разделяются символами новой строки, но поскольку мы делаем многострочные шаблоны, это создает неудобства, из-за которых мы не можем легко извлечь отдельные совпадения.Как сделать вывод grep отдельным символом NULL?

Пример

grep -rzPIho '}\n\n\w\w\b' | od -a 

В зависимости от файлов в вашем дереве файлов, это может привести выход как

0000000 } nl nl m y nl } nl nl i f nl } nl nl m 
0000020 y nl } nl nl m y nl } nl nl i f nl } nl 
0000040 nl m y nl 
0000044 

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

Что не работает

Сейчас на --null (или -Z) работает только в сочетании с -l, что делает Grep только список имен файлов вместо матчей, так что здесь не поможет.

Обратите внимание, что это не дубликат Is there a grep equivalent for find's -print0 and xargs's -0 switches?, так как требования к этому вопросу различны, что позволяет ему отвечать альтернативными методами.

Итак, как мы можем сделать эту работу? Может быть, использовать grep в сочетании с другими инструментами?

+1

Я собираюсь пойти с «вы не можете» здесь, если 'grep' сам не может сделать это для вас (и кто скажет, что у вас нет' NUL' в ваших совпадающих данных для начала) , Вы уже злоупотребляли 'grep', чтобы сделать эту работу уже. Я либо использовал вывод «od» (или аналогичный), либо использовал инструмент, отличный от 'grep', который вы могли бы лучше контролировать вывод (' awk' или 'perl' или что-то еще). –

+0

Кортеж имени файла, смещения байта и длины совпадения позволит вам собирать фактические совпадения, когда они вам понадобятся. Я не думаю, что это выполнимо с 'grep', но реализация этого в Python или Perl не должна быть трудной. – tripleee

+0

Можете ли вы добавить образец текста к вашему вопросу и ожидаемый результат? Я также рекомендовал бы использовать 'awk' для этого. – miken32

ответ

3

Я подал этот вопрос как запрос признака в Grep ошибке список рассылки GNU, и оказалось, что это ошибка в коде.

Это было исправлено и подтолкнул к хозяину, поэтому он будет доступен в следующей версии GNU Grep: http://git.savannah.gnu.org/cgit/grep.git/commit/?id=cce2fd5520bba35cf9b264de2f1b6131304f19d2

Резюмируя: этот патч убеждается, что -z флаг работает не только в сочетании с -l, но и с -o.

1

Что приходит в мой ум будет использовать разделитель групп, например, что-то вроде:

grep -rzPIho '}\n\n\w\w\b' $FILE -H | sed "s/^$FILE:/\x0/" 
+0

Да, это выглядит довольно просто. Не полностью доказательство, если у вас очень короткие файлы, но +1. Нуждается в дополнительной логике при работе с большими файлами. Btw –

+0

Да, это не совсем безупречно и нуждается в улучшении; это также зависит от содержимого файла. Пожалуйста, сообщите нам, если вы придумаете лучшее решение: ^) – bufh

+0

Проверьте мой последний ответ –

1

Вот еще один способ сделать это, которые должны быть более надежными, чем @bufh писал, но также сложнее и медленнее.

$ grep -rIZl '' --include='*.pl'| xargs -0 cat | dos2unix | tr '\n\0' '\0\n' \ 
     | grep -Pao '}\x00\x00\w\w\b' | tr '\0\n' '\n\0' | od -a 

dos2unix, очевидно, необходим только при работе с окончанием строки Windows. Таким образом, пуанлинг здесь заключается в том, что мы заменяем нулевые байты символами новой строки на входе, вместо этого имеем grep match вместо nullbytes и меняем места обратно.

0000000 } nl nl m y nul } nl nl i f nul } nl nl m 
0000020 y nul } nl nl m y nul } nl nl i f nul } nl 
0000040 nl m y nul 
0000044 
Смежные вопросы