Як отримати текст із діапазону дат, використовуючи grep / sed у великому текстовому файлі?


9

У мене великий файл тексту (майже 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>

Як я можу це отримати?


2
Ви впевнені, що маєте на увазі червень ? Усі дати у вашому файлі журналу зразка припадають на липень, а бажаний вихідний зразок означає, що ви мали на увазі останню.
Девід Фоерстер

Відповіді:


13

З , grepякщо ви знаєте кількість рядків ви хочете , ви можете використовувати опцію контекстної -Aдрукувати рядки після шаблону

grep -A 3 2016-07-13 file

це дасть вам лінію з 2013-07-13 та наступні 3 рядки

з sedви можете використовувати дати , щоб розмежувати , як це

sed -n '/2016-07-13/,/2016-07-19/p' file

який надрукує всі рядки з першого рядка з 2016-07-13 до та включаючи перший рядок з 2016-07-19. Але це передбачає, що у вас є лише один рядок з 2016-07-19 (він не буде друкувати наступний рядок). Якщо є кілька рядків, використовуйте наступну дату замість неї та використовуйте dдля видалення результатів з неї

sed -n '/2016-07-13/,/2016-07-20/{/2016-07-20/d; p}' file

11

Цього простого затиску одного вкладиша буде достатньо:

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

Тут чудово працює і немає потреби в sed :)

Список літератури:


1
Як завжди ви приносите благодать :)
Zanna

(у) ... довелося видалити, ^щоб це працювало. Використання Mac.
Анум Шераз

4

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


4

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

Я представляю цей сценарій 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функції, відповідно до нього.


3

Ви могли зробити це поетапно. Знайдіть номер першого рядка, що відповідає вашому вихідному шаблону. Знайдіть номер останнього рядка, що відповідає вашому кінцевому шаблону. Потім витягніть тест між цими двома рядками. Це можна зробити наступним чином.

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 && NR <= 5678), дією за замовчуванням є друк рядків у цьому діапазоні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.