У меня есть большой текст файла (почти 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>
Как я могу получить это?
С grep
, если Вы знаете количество строк, Вы хотите Вас, может использовать опцию -A
контекста распечатать строки после шаблона
grep -A 3 2016-07-13 file
, который даст Вам строку с 13.07.2013 и следующие 3 строки
с sed
, можно использовать даты для разграничивания как это
sed -n '/2016-07-13/,/2016-07-19/p' file
, который распечатает все строки от первой строки с 13.07.2016 до и включая первую строку с 19.07.2016. Но это предполагает, что у Вас есть только одна строка с 19.07.2016 (она не распечатает следующую строку). Если существует несколько строк, используют следующую дату вместо этого и используют d
для удаления вывода из него
sed -n '/2016-07-13/,/2016-07-20/{/2016-07-20/d; p}' file
Этот простой grep один лайнер будет достаточно:
grep -E ^2016-07-1[3-9] filename
Работы приятно тут и там не потребность в sed :)
Ссылки:
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
Вы могли сделать это на шагах. Найдите количество первой строки, соответствующей Вашему стартовому шаблону. Найдите количество последней строки, соответствующей Вашему конечному шаблону. Затем извлеките тест между этими двумя строками. Это может быть сделано следующим образом.
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 НОМЕР переменной является текущим номером строки, и так как никакое действие не было указано после шаблона (НОМЕР> =1234 & & NR< =5678), действие по умолчанию должно распечатать строки это в том диапазоне.
Все другие текущие ответы полагаются на то, что записи файла журнала отсортированы хронологически или то, что диапазон дат может быть подобран легко с регулярными выражениями. Если Вы хотите более универсальное решение, мы должны сделать еще некоторое программирование.
Я представляю этот сценарий AWK GNU:
#!/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
функционируйте для удовлетворения ему.