Как получить текст из диапазона дат, используя grep / sed в большом текстовом файле?

У меня большой файл (почти 3 ГБ) - это файл журнала. Я хочу получить строки текста, соответствующие диапазону дат из этого файла, с 13 июля по 19 июля. Формат моего журнала:

2016-07-12 < ?xml version>
2016-07-13 < ?xml version>
2016-07-18 < ?xml version>
2016-07-18 < ?xml version>
2016-07-19 < ?xml version>
2016-07-20 < ?xml version>
sample text sample text
sample text sample text
sample text sample text
2016-07-20 < ?xml version>
sample text sample text
2016-07-20 < ?xml version>

, поэтому после grep / sed он должен быть выведен следующим образом:

2016-07-13 < ?xml version>
2016-07-18 < ?xml version>
2016-07-18 < ?xml version>
2016-07-19 < ?xml version>

Как я могу это получить? [!d2 ]

1
задан 20 July 2016 в 14:52

4 ответа

Этот простой grep один вкладыш будет достаточным:

grep -E ^2016-07-1[3-9] filename

Хорошо работает здесь, и нет необходимости в sed:)

Ссылки:

Соответствующие числовые диапазоны с регулярным выражением
9
ответ дан 23 May 2018 в 07:58

Все остальные текущие ответы основаны на том, что записи в файле журнала сортируются хронологически или тот факт, что диапазон дат можно легко сопоставить с регулярными выражениями. Если вы хотите получить более общее решение, нам нужно сделать еще несколько программ.

Я представляю этот скрипт GNU AWK:

#!/usr/bin/gawk -f
BEGIN {
    starttime = mktime(starttime)
    endtime = mktime(endtime)
}

func in_range(n, start, end) {
    return start <= n && n < end
}

match($0, /^([0-9]{4})-([0-9]{2})-([0-9]{2})\s/, m) &&
    in_range(mktime(m[1] " " m[2] " " m[3] " 00 00 00"), starttime, endtime)

Вы отправляете начальное и конечное время через переменные starttime и endtime в формате, который понимает mktime (YYYY MM DD hh dd ss). Таким образом, вы запускаете команду awk так, считая, что вышеуказанный сценарий Awk находится в исполняемом файле filter-log-dates.awk в текущем рабочем каталоге, а файл журнала - mylog.txt:

./filter-log-dates.awk -v starttime='2016 07 13 00 00 00' -v endtime='2016 07 20 00 00 00' mylog.txt

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

Если ваш формат штампа времени отличается, вы можете настроить регулярное выражение, переданное функции match, в соответствии с этим.

4
ответ дан 23 May 2018 в 07:58

awk решение:

$ awk '/^2016-07-13.*/,/2016-07-19.*/'  input.txt                                   
2016-07-13 < ?xml version> 
2016-07-18 < ?xml version> 
2016-07-18 < ?xml version> 
2016-07-19 < ?xml version> 

В основном печатает любую строку из той, которая начинается с 2016-07-13, с той, которая начинается с 2016-07-19

3
ответ дан 23 May 2018 в 07:58

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

grep -n 2016-07-13 bigtextfile | head -1
grep -n 2016-07-19 bigtestfile | tail -1
# Say the first number is 1234 and the second 5678, then use...
awk 'NR>=1234 && NR<=5678' bigtestfile > rangeoftext

Это можно сделать все в команде awk, но шаги могут упростить выполнение. Внутри awk переменная NR является текущим номером строки, и поскольку после шаблона (NR> = 1234 & amp; & amp; NR = 5678) не было указано действие, действие по умолчанию заключается в том, чтобы печатать строки, которые находятся в этом диапазоне. [!d1 ]

2
ответ дан 23 May 2018 в 07:58

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

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