2 Stimmen

Wie man mehrere Parameter aus einem String mit sed oder awk extrahiert

Ich habe eine Protokolldatei, die so aussieht:

2010/01/12/ 12:00 einige irrelevante alapha 129495 und der interessante Wert 45pts
2010/01/12/ 15:00 einige irrelevante alapha 129495 und kein interessanter Wert
2010/01/13/ 09:00 einige irrelevante alapha 345678 und der interessante Wert 60pts

Ich möchte die Datum-Zeit-Zeichenfolge vs. interessanten Wert mit gnuplot plotten. Um das zu tun, versuche ich die obige Protokolldatei in eine CSV-Datei zu parsen, die wie folgt aussieht (nicht alle Zeilen im Protokoll haben einen plottbaren Wert):

2010/01/12/ 12:00, 45

2010/01/13/ 14:00, 60

Wie kann ich das mit sed oder awk machen?

Ich kann die Anfangszeichenfolgen extrahieren, so etwas wie:

cat partial.log | sed -e 's/^\(.\{17\}\).*/\1/' 

aber wie kann ich die Endwerte extrahieren?

Ich habe versucht, dies zu tun, leider ohne Erfolg!

Vielen Dank

1voto

Chris Punkte 2967

Versuch:

awk 'NF==12{sub(/pts/,"",$12);printf "%s %s, %s ", $1, $2, $12}' Datei

Eingabe:

2010/01/12/ 12:00 etwas irrelevantes alapha 129495 und der interessante Wert 45pts
2010/01/12/ 15:00 etwas irrelevantes alapha 129495 und kein interessanter Wert
2010/01/13/ 09:00 etwas irrelevantes alapha 345678 und der interessante Wert 60pts

Ausgabe:

2010/01/12/ 12:00, 45 2010/01/13/ 09:00, 60

Aktualisiert für Ihre neuen Anforderungen:

Befehl:

awk 'NF==12{gsub(/\//,"-",$1)sub(/pts/,"",$12);printf "%s%s %s \n", $1, $2, $12}' Datei 

Ausgabe:

2010-01-12-12:00 45 
2010-01-13-09:00 60

Ich hoffe, das hilft. Chris

1voto

bash-o-logist Punkte 6407

Bash

#!/bin/bash

while read -r a b line
do
  [[ $line =~ ([0-9]+)pts$ ]] && echo "$a $b, ${BASH_REMATCH[1]}"
done < file

1voto

theozh Punkte 19006

Auch wenn dies eine wirklich alte Frage mit vielen Antworten ist, können Sie es ohne die Verwendung externer Tools wie sed oder awk tun (und daher plattformunabhängig). Sie können es "einfach" mit gnuplot machen (auch mit der Version zum Zeitpunkt der Frage des OP: gnuplot 4.4.0, März 2010).

Es ist jedoch aus Ihren Beispieldaten und Ihrer Beschreibung nicht klar, ob der interessante Wert

  1. streng in der 12. Spalte steht oder
  2. immer in der letzten Spalte steht oder
  3. in einer beliebigen Spalte stehen kann, jedoch immer von pts gefolgt wird

Für alle 3 Fälle gibt es nur mit gnuplot (und daher plattformunabhängig) Lösungen. Die Annahme ist, dass der Spalten-Trenner ein Leerzeichen ist.

ad 1. Die einfachste Lösung: mit u 1:12 ignoriert gnuplot einfach nicht-numerische und Spaltenwerte, z.B. wird 45pts als 45 interpretiert.

ad 2. und 3. Wenn Sie die letzte Spalte als Zeichenfolge extrahieren, wird gnuplot fehlschlagen und stoppen, wenn Sie einen nicht-numerischen Wert über real() in eine Gleitkommazahl umwandeln möchten. Daher müssen Sie selbst über Ihre eigene Funktion isNumber() testen, ob der Spaltenwert zumindest mit einer Nummer beginnt und daher durch real() konvertiert werden kann. Falls die Zeichenfolge keine Zahl ist, könnten Sie den Wert auf 1/0 oder NaN\=4.6.0) könnten Sie den Wert auf NaNset datafile missing NaN vermeiden, das jedoch in gnuplot 4.4 nicht verfügbar ist. Außerdem wird in gnuplot 4.4 NaN einfach auf 0.0 gesetzt (GPVAL_NAN = 0.0). Sie können dies mit diesem "Trick" umgehen, der auch unten verwendet wird.

Daten: SO7353702.dat

2010/01/12/ 12:00 einige irrelevante Alapha 129495 und der interessante Wert 45pts
2010/01/12/ 15:00 einige irrelevante Alapha 129495 und kein interessanter Wert
2010/01/13/ 09:00 einige irrelevante Alapha 345678 und der interessante Wert 60pts
2010/01/15/ 09:00 einige irrelevante Alapha 345678 62pts und nichts
2010/01/17/ 09:00 einige irrelevante Alapha 345678 und nichts
2010/01/18/ 09:00 einige irrelevante Alapha 345678 und der interessante Wert 70.5pts
2010/01/19/ 09:00 einige irrelevante Alapha 345678 und der interessante Wert extra extra 64pts
2010/01/20/ 09:00 einige irrelevante Alapha 345678 und der interessante Wert 0.66e2pts

Skript: (funktioniert für gnuplot>=4.4.0, März 2010)

### Zahlen ohne externe Tools extrahieren
reset
DATEI = "SO7353702.dat"

set xdata time
set timefmt "%Y/%m/%d/ %H:%M"
set format x "%b %d"
isNumber(s) = strstrt('+-.',s[1:1])>0 && strstrt('0123456789',s[2:2])>0 \
              || strstrt('0123456789',s[1:1])>0

# Version 1:
plot DATEI u 1:12 w lp pt 7 ti "Wert in der 12. Spalte"
pause -1

# Version 2:
set datafile separator "\t"
getLastValue(col) = (s=word(strcol(col),words(strcol(col))), \
                     isNumber(s) ? (t0=t1, real(s)) :  (y0))
plot t0=NaN DATEI u (t1=timecolumn(1), y0=getLastValue(1), t0) : (y0) w lp pt 7 \
        ti "Wert in der letzten Spalte"
pause -1

# Version 3:
getPts(s) = (c=strstrt(s,"pts"), c>0 ? (r=s[1:c-1], p=word(r,words(r)), isNumber(p) ? \
            (t0=t1, real(p)) : y0) : y0)
plot t0=NaN DATEI u (t1=timecolumn(1),y0=getPts(strcol(1)),t0):(y0) w lp pt 7 \
            ti "Wert überall mit 'pts' am Ende"
### Ende des Skripts

Ergebnis:

Version 1:

Bildbeschreibung hier eingeben

Version 2:

Bildbeschreibung hier eingeben

Version 3:

Bildbeschreibung hier eingeben

0voto

carlpett Punkte 11327

Es ist tatsächlich möglich. Ein Regex wie dieser zum Beispiel:

sed -n 's!([0-9]{4}/[0-9]{2}/[0-9]{2}/ [0-9]{2}:[0-9]{2}).*([0-9]+)pts!\1, \2!p'

0voto

Kent Punkte 180747
awk '/pts/{ gsub(/pts/,"",$12);print $1,$2", "$12}' yourFile

output:

2010/01/12/ 12:00, 45
2010/01/13/ 09:00, 60

[Aktualisierung:basierend auf Ihrer neuen Anforderung]

Wie kann ich das obige so ändern, dass es wie folgt aussieht:

2010-01-12-12:00 45 
2010-01-13-09:00 60
awk '/pts/{ gsub(/pts/,"",$12);a=$1$2OFS$12;gsub(/\//,"-",a);print a}' yourFile

Der oben genannte Befehl gibt Ihnen:

2010-01-12-12:00 45
2010-01-13-09:00 60

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X