Скрипт Unix для поиска в сжатом файле .gz - PullRequest
3 голосов
/ 12 ноября 2010

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

Файл .gz содержит много текстовых файлов, и я хочу найти строку во всех этих текстовых файлах, и мне нужночтобы получить предыдущие 3 строки в качестве вывода, включая текущую строку (где присутствует строка поиска).

Я попытался zgrep и получил номер строки, но когда я использую head или tailКоманда Это дает некоторые значения мусора.Я думаю, что мы не можем использовать команды head или tail для сжатых файлов, содержащих несколько файлов.

Пожалуйста, предложите, если есть какой-нибудь простой способ?

Ответы [ 2 ]

5 голосов
/ 12 ноября 2010

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

tar -tzf file.tar.gz | grep '\.txt' | xargs tar -Oxzf file.tar.gz | grep -B 3 "string-or-regex" объединит все файлы в .tar.gzс именами, оканчивающимися на ".txt", и grep их для данной строки, также выводя 3 предыдущие строки.Он не скажет вам, из какого файла в тарболе пришло какое-либо совпадение, и «три предыдущие строки» могут фактически исходить из предыдущего файла.

Вместо этого вы можете сделать:

for file in $(tar -tzf file.tar.gz | grep '\.txt'); do 
    tar -Oxzf file.tar.gz "$file" | grep -B 3 --label="$file" -H "string-or-regex"
done

, который будет учитывать границы файлов и сообщать имена файлов, но будет гораздо менее эффективным.

(-z сообщает tar, что он gzip сжат. -t перечисляет содержимое. -x extracts. -O перенаправляет на стандартный вывод, а не на файловую систему. Старые tar s могут не иметь флага -O или -z и будут хотеть флаги без -: например, tar tz file.tar.gz)

Хорошо, значит у вас непригодный grep.Мы можем исправить это с помощью awk!

#!/usr/bin/awk -f
BEGIN { context=3; }
{ add_buffer($0) }
/pattern/ { print_buffer() }
function add_buffer(line)
{
    buffer[NR % context]=line
}
function print_buffer()
{
    for(i = max(1, NR-context+1); i <= NR; i++) {
        print buffer[i % context]
    }
}
function max(a,b)
{
    if (a > b) { return a } else { return b }
}

Это не объединит смежные совпадения, в отличие от grep -B, и, таким образом, может повторять строки, которые находятся в пределах 3 строк двух разных совпадений.

0 голосов
/ 12 ноября 2010

Это может быть gzip файла tar? Самое простое - просто извлечь все и использовать обычные инструменты для извлеченных файлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...