Kann jemand erklären, warum diese Mustererkennung mit sed nicht funktioniert

2

Es wurde versucht, bestimmte Zeiten von Protokollen basierend auf der Empfehlung von auszudrucken diese Thread von Superuser. Ich bin mir nicht sicher, warum meine Muster nicht mit sed übereinstimmen. Ich habe das Beispieldatum und die Uhrzeit, die ich verwende, eingefügt Hier . Wenn ich benutze

sed -n '/2014-03-27 07:00:00/ , /2014-03-27 11:25:00/p' log-file-name

Ich erwarte, dass es alle Zeilen druckt, die zwischen 7.00 und 11.00 Uhr übereinstimmen. Aber ich bekomme keine Treffer. Wenn ich "-n" entferne, werden als Ergebnis die gesamten Zeilen von 3 Uhr morgens bis 16:14 Uhr gedruckt. Ich habe versucht, den obigen sed-Befehl mit einfachen und doppelten Anführungszeichen zu optimieren und habe verschiedene Abstandsoptionen ausprobiert. Aber die Ergebnisse sind immer "alle oder keine". Kann jemand bitte erklären, warum sed die Zeilen für das Stundenfenster nicht druckt, um das ich es bitte zu drucken?

user2476714
quelle
1
Wäre schön, wenn Sie einen Teil der Datei einfügen, die Sie sich ansehen möchten. Sind Sie sicher, dass zwischen Datum und Uhrzeit NUR ein Leerzeichen steht? Sind Sie auch sicher, dass es sich um einen SPACE und nicht um einen TAB handelt?
mdpc

Antworten:

1

Sie versuchen, sed mit der Funktion zum Starten und Stoppen von Mustern zu verwenden.

Wenn also eine Zeile gefunden wird, die Ihrem ersten (Start-) Muster entspricht, wird die Ausgabe solange zurückgegeben, bis eine Zeile gefunden wird, die dem zweiten (Stopp-) Muster entspricht.

Wenn die Startzeile in Ihrer Datei nicht genau vorhanden ist, erhalten Sie keine Ergebnisse.

Wenn Sie die Option -n aus Ihren Optionen entfernen, werden alle gedruckt, auch wenn sie nicht mit Ihrem Muster übereinstimmen. Wenn Sie sed mit -n '/.../p' verwenden, verhält es sich wie grep.

Ich habe ein nützliches Tutorial gefunden Hier

Für Ihren Fall könnten Sie ein Muster in etwa wie folgt betrachten:

\d{4}-\d{2}-\d{2} ((0[7-9])|(1[0-1])):\d{2}:\d{2},\d{3}

Die oben genannten Werte passen alle Zeiten von 07:00 bis 11:59
einige erklärungen:
\d{4} = match 4 digits (year, eg. 2014)
(0[7-9]) = match 07 - 09
| = OR
(1[0-1]) = match 10 -11

Loopo
quelle
Das war's. Es war in der Tat das Start- und Stoppmuster, das sich nicht in der von mir gesuchten Protokolldatei befand. Ich schlug mit dem Kopf gegen den Schreibtisch, weil das in der Vergangenheit für mich funktionierte und plötzlich nicht mehr funktionierte. Vielen Dank für den Link zu diesem wunderbaren Tutorial. Das ist eines der besten Tutorials, die ich je gesehen habe. Leider kann ich dir keine Upvotes geben, da ich auf dieser Seite keinen guten Ruf habe :(.
user2476714
0

Unix ist großartig, wenn es darum geht, kleine Dinge zu tun, aber nicht zu lange. Dies nimmt die awk vom verlinkten Post und fügt eine Date-Pipe hinzu.

Dies findet alle Daten am Anfang der Zeile mit 2014-03-27, Nimmt diese Ausgabe und findet alle Zeiten mit Stunden (zweites Feld) oder gleich 7 und kleiner als 11.

grep ^2014-03-27 log-file | awk -F'[: ]' '$2 >= 7 && $2 < 11 { print }'
Michael Tomkins
quelle
Vielen Dank . Das funktioniert fast bei mir. Aber ich habe noch ein Problem. Wie verwende ich es, wenn ich die Zeit genauer bestimmen muss? Zum Beispiel: von 7:30 bis 8:30 Uhr. Ich habe herausgefunden, wie es geht, wenn es in derselben Stunde ist, zum Beispiel: "grep ^ 2014-02-20 Protokolldateiname | awk -F '[:]' '$ 2 & gt; = 7 & amp; & amp; $ 2 & lt; 8 & amp; & amp; $ 3 & gt; 35 & amp; $ 3 & lt; 45 {print} '"scheinen zu funktionieren. Aber ich bin nicht sicher, wie es für Filter geht, die stündliche Grenzen wie 7:30 Uhr bis 8:30 Uhr überschreiten
user2476714
Ich mache es mit einer logischen Trennung. Zeile 1, Stunde bis zum Ende. Linie 2, Mittlere Stunde. Linie 3, Stunde, die zu einer Minute geht. so 7:35 - 10-25 grep ^ 2014-02-20 log-dateiname | awk -F '[:]' '$ 2 = 7 & amp; & amp; $ 3 & gt; = 35 {print} '"grep ^ 20.02.2014 Protokolldateiname | awk -F' [:] '' $ 2 & gt; = 8 & amp; & amp; $ 2 & lt; 10 {print} 'grep ^ 2014-02-20 Protokolldateiname | awk -F '[:]' '$ 2 = 10 & amp; & amp; $ 3 & lt; 25 {print}' Ja, es ist nicht klein, aber lesbar und logisch sauber Sie möchten, dass die Antwort von Scrutinizer genau stimmt.
Michael Tomkins
0

Mit Regex wird es kompliziert. Vielleicht reicht so etwas aus:

awk '$1 FS $2>=s{p=1} $1 FS $2>e{exit}p' s="2014-03-27 07:00:00" e="2014-03-27 11:25:00" file

Erläuterung:

awk '
  $1 FS $2>=s{     # `$1 FS $2` is the string the consists of field 1, a space, 
                   # and field 2. If it is larger or equal (string comparison) 
                   # to the variable s, then: 
    p=1            # set a variable p to 1
  }
  $1 FS $2>e{      # if the string $1 FS $2 is larger than variable e, then
    exit           # exit the script ( stop processing the file )
  }
  p                # if variable p is equal to 1 then print the record (line)
' s="2014-03-27 07:00:00" e="2014-03-27 11:25:00" file    
                   # line above: set variables p and s and specify file name

$1 FS $2 Ist die Zeichenkette, die aus Feld 1, einem Leerzeichen und Feld 2 besteht. Wenn sie größer oder gleich der Variablen s ist (Zeichenkettenvergleich), setzen Sie eine Variable p auf 1

Scrutinizer
quelle
Dies wäre der einfachste Weg gewesen. Aber leider gibt es mir keine Treffer. Ich bekomme gerade die Eingabeaufforderungszeichenfolge zurück. Ich versuche, das Problem selbst zu erkennen und zu prüfen, ob ich es beheben kann, aber ehrlich gesagt weiß ich nicht, was "$ 2 = s {p = 1}" bedeutet.
user2476714
@ user2476714: Hinzugefügt und erklärt. Ich hoffe es hilft..
Scrutinizer