Chcę wyodrębnić wszystkie dzienniki między dwoma znacznikami czasu. Niektóre linie mogą nie mieć znacznika czasu, ale chcę też te linie. Krótko mówiąc, chcę, aby każda linia mieściła się w dwóch znacznikach czasu. Moja struktura dziennika wygląda następująco:
[2014-04-07 23:59:58] CheckForCallAction [ERROR] Exception caught in +CheckForCallAction :: null
--Checking user--
Post
[2014-04-08 00:00:03] MobileAppRequestFilter [DEBUG] Action requested checkforcall
Załóżmy, że chcę wyodrębnić wszystko między 2014-04-07 23:00
i 2014-04-08 02:00
.
Pamiętaj, że w dzienniku może nie być znacznika czasu rozpoczęcia lub zakończenia, ale chcę mieć każdą linię między tymi dwoma znacznikami czasu.
text-processing
sed
awk
grep
Amit
źródło
źródło
date -d
polecenia i wykorzystując je do skonstruowania wzorca wyszukiwania.Odpowiedzi:
Możesz użyć
awk
do tego:Gdzie:
-F
określa znaki[
i]
separatory pól za pomocą wyrażeń regularnych$0
odwołuje się do pełnej linii$2
odwołuje się do pola datyp
jest używany jako zmienna logiczna, która chroni rzeczywiste drukowanie$0 ~ /regex/
jest prawdziwe, jeśli wyrażenie regularne pasuje$0
>=
służy do leksykograficznego porównywania łańcucha (odpowiednik np.strcmp()
)Wariacje
Powyższy wiersz poleceń implementuje dopasowanie przedziału czasu po prawej stronie . Aby uzyskać semantykę zamkniętych interwałów, po prostu zwiększ swoją właściwą datę, np .:
Jeśli chcesz dopasować znaczniki czasu w innym formacie, musisz zmodyfikować
$0 ~ /^\[/
podwyrażenie. Zauważ, że kiedyś ignorowało linie bez żadnych znaczników czasu z logiki drukowania / wyłączania.Na przykład dla formatu znacznika czasu, takiego jak
YYYY-MM-DD HH24:MI:SS
(bez[]
nawiasów klamrowych), możesz zmodyfikować polecenie w następujący sposób:(zwróć uwagę, że zmieniany jest również separator pól - domyślnie przejście na puste / niepuste)
źródło
$1 ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}/ && $2 ~/[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/ { Time = $1" "$2; if (Time >= "2014-04-07 23:00" ) { p=1 } if (Time >= "2014-04-08 02:00:01" ) { p=0 } } p
code
0 ~ / ^ [az | AZ] {4} - [0-9] {2} - [0-9] {4} [0-2] [0-9 ]: [0-5] [0-9]: [0-5] [0-9] / && $ 1 "" 2 $> = "Apr-07-2014 11:00" {p = 1} 0 ~ / ^ [az | AZ] {4} - [0-9] {2} - [0-9] {4} [0-2] [0-9]: [0-5] [0-9]: [0 -5] [0-9] / && $ 1 "" 2 $> = "Apr-07-2014 12:00:01" {p = 0},code
ale nie działaSprawdź
dategrep
na https://github.com/mdom/dategrepOpis:
Przykłady użycia:
Chociaż to ograniczenie może sprawić, że nie będzie to właściwe dla twojego dokładnego pytania:
źródło
Jedną alternatywą
awk
lub niestandardowym narzędziem jest użycie GNUgrep
dla jego kontekstowych greps. GNUgrep
pozwoli ci określić liczbę linii po pozytywnym dopasowaniu do wydrukowania-A
i poprzednie linie do wydrukowania-B
na przykład:Powyższe zasadniczo mówi
grep
o wydrukowaniu 10 000 linii następujących po linii, która odpowiada wzorowi, od którego chcesz zacząć, skutecznie powodując, że twój wydruk zaczyna się tam, gdzie chcesz i trwa do końca (miejmy nadzieję), podczas gdy drugiegrep
w potok mówi mu, aby drukował tylko linię z ogranicznikiem końcowym i 10 000 linii przed nią. Końcowym rezultatem tych dwóch czynności jest rozpoczęcie tam, gdzie chcesz, a nie przejście do miejsca, w którym kazałeś to zatrzymać.10 000 to tylko liczba, którą wymyśliłem, możesz ją zmienić na milion, jeśli uważasz, że Twoje wyniki będą zbyt długie.
źródło
sed
co również szuka dosłownych dopasowań.dategrep
jest prawdopodobnie najbardziej poprawną odpowiedzią ze wszystkich podanych (ponieważ musisz być w stanie „rozmyć”, jakie znaczniki czasu akceptujesz), ale jak mówi odpowiedź, właśnie wspomniałem o tym jako alternatywę. To powiedziawszy, jeśli dziennik jest wystarczająco aktywny, aby wygenerować wystarczającą moc wyjściową, aby uzasadnić cięcie, prawdopodobnie będzie miał również jakiś wpis dla danego okresu czasu.Za pomocą sed:
Skopiuj to do pliku. Jeśli nie chcesz widzieć informacji o debugowaniu, debugowanie jest wysyłane do stderr, więc po prostu dodaj „2> / dev / null”
źródło