Ich habe die folgenden Details aus der verarbeiteten Abfrage:
queuename qtype resv/used/tot. np_load arch states --------------------------------------------------------------------------------- abax55@lp55cs008 BP 0/36/36 1.08 lx-amd64 gf:app_monitor=1 gf:app_abaqus=1 gf:app_abaqusfgs=1 gf:app_actran=1 hl:load_avg=38.980000 hl:load_short=38.550000 hl:load_medium=38.980000 hl:load_long=39.030000
I. Ich möchte nur hl:load_avg=38.980000
mit dem Präfix abax55@lp55cs008
erfassen. Dies bedeutet, dass die Ausgabe folgendermaßen aussehen sollte:
abax55@lp55cs008 - hl:load_avg=38.980000
…. dies ist nur für einen Computer mit dem Namen cs008
. und die Gesamtzahl der Maschinen wäre 100+.
Bitte schlagen Sie zwei Optionen vor:
- , um nur eine bestimmte Maschine zu erfassen,
- um alle zu erfassen Maschinen
Kommentare
- alle Maschinen – Wie lautet die Namenskonvention für alle Maschinen? Haben sie ein gemeinsames Präfix in ihren Namen?
- abax55 @ lp55cs001 abax55 @ lp55cs002 abax55 @ lp55cs003 abax55 @ lp55cs004 …. so weiter!
- meine einzige Eingabe für diesen gesamten Abfrage sollte ‚ abax55 ‚ sein, alles muss per Shell erledigt werden
- Ihre Frage ist noch unklar und muss es ist grep? Wenn das Greppen in einem Fall einfach ist, drucken Sie diesen Text vor dem Ergebnis aus.
- Verwenden Sie grep
rep -o "hl:load_avg=38.980000" machines | xargs -L 1 echo "abax55@lp55cs008 -"
oder awkawk 'match($0,/hl:load_avg=38.980000/) { print "abax55@lp55cs008 - " substr($0,RSTART,RLENGTH) }' machines
Antwort
Awk
Lösung:
1) um nur eine bestimmte Maschine zu erfassen:
awk -v m="cs008" "/abax55@lp55cs[0-9]/ && $1 ~ m{ m_name=$1 } m_name && /hl:load_avg=/{ print m_name" - "$1; exit }" file
Die Ausgabe:
abax55@lp55cs008 - hl:load_avg=38.980000
2) zum Erfassen aller Maschinen:
awk "/abax55@lp55cs[0-9]/{ m_name=$1 } m_name && /hl:load_avg=/{ print m_name" - "$1; m_name=0 }" file
Kommentare
- Ist es möglich, den gesamten Befehl in einer einzigen Zeile auszuführen?
- @Nayak, arbeiten Sie Ihre Frage aus, es klingt vage
- ist es möglich, ‚ awk -vm = “ cs008 “ ‚ / abax55 @ lp55cs [0-9] / & & $ 1 ~ m {m_name = $ 1} awk -vm = “ cs008 “ ‚ / abax55 @ lp55cs [0-9] / & & $ 1 ~ m {m_name = $ 1} ‚ in einer einzelnen Zeile?
- ja. Dies kann alles in einer Zeile ausgeführt werden. Ersetzen Sie die Zeilenumbrüche im zitierten awk-Skript durch
;
-Zeichen. (Eine oder beide Zeilenumbrüche und;
können verwendet werden, um Anweisungen inawk
zu trennen.) - sehr einfache Lösung und die Laufzeit ist niedrig …. vielen Dank
Antwort
Zum Testen habe ich den gleichen Inhalt eingefügt in Datei mehrmals durch Ändern der Hostnamen in Datei
input file queuename qtype resv/used/tot. np_load arch states --------------------------------------------------------------------------------- abax55@lp55cs008 BP 0/36/36 1.08 lx-amd64 gf:app_monitor=1 gf:app_abaqus=1 gf:app_abaqusfgs=1 gf:app_actran=1 hl:load_avg=38.980000 hl:load_short=38.550000 hl:load_medium=38.980000 hl:load_long=39.030000 queuename qtype resv/used/tot. np_load arch states --------------------------------------------------------------------------------- abax55@lp55cs009 BP 0/36/36 1.08 lx-amd64 gf:app_monitor=1 gf:app_abaqus=1 gf:app_abaqusfgs=1 gf:app_actran=1 hl:load_avg=38.980000 hl:load_short=38.550000 hl:load_medium=38.980000 hl:load_long=39.030000 queuename qtype resv/used/tot. np_load arch states --------------------------------------------------------------------------------- abax55@lp55cs007 BP 0/36/36 1.08 lx-amd64 gf:app_monitor=1 gf:app_abaqus=1 gf:app_abaqusfgs=1 gf:app_actran=1 hl:load_avg=38.980000 hl:load_short=38.550000 hl:load_medium=38.980000 hl:load_long=39.030000
Befehl
for i in `sed -n "/abax55@lp55cs/p" file.txt |awk "{print $1}"`; do sed -n "/$i/,+5p" file.txt | awk "{print $1}" | sed -n -e "1p" -e "$p" | perl -pne "s/\n/-/"| sed "s/-$/\n/g"; done
Ausgabe
abax55@lp55cs008-hl:load_avg=38.980000 abax55@lp55cs009-hl:load_avg=38.980000 abax55@lp55cs007-hl:load_avg=38.980000
Kommentare
- @Nayak Können Sie für eine Antwort stimmen
Antwort
Ich würde grep
Ich würde :
#!/usr/bin/env perl use strict; use warnings; use Data::Dumper; my %values = do { local $/; <> } =~ m/(\w+\@\w+).*?hl:load_avg=([\d\.]+)/gms; print Dumper \%values; print $values{"abax55@lp55cs008"}
Ich kann es wahrscheinlich verfeinern, wenn Sie ein spezifischeres Aufzeichnungsformat angeben können. Sie können die gesamte Zeilengruppe jedoch leicht genug in einen Block zerlegen, da jeder neue „Block“ zu Beginn kein Leerzeichen enthält (es ist sogar noch einfacher, wenn zwischen den Datensätzen ein klares Trennzeichen vorhanden ist, z. B. eine Leerzeile, jedoch ohne zu sehen Ihre Ausgabe kann ich nicht sagen, was das wäre).
#!/usr/bin/env perl use strict; use warnings; use Data::Dumper; my $current_host = ""; my %values; #<> reads stdin or files specified on command line. #if that doesn"t work for you, you can "open" a specific file, or #use qx() or backticks to run a a command. while ( <> ) { #match a regex and capture the result if it"s valid. if ( m/^(\w+\@\w+)/ ) { $current_host = $1 }; #lines that start with whitespace are the values. if ( m/^\s+(\w+:\w+)=([\d\.]+)/ ) { #$1 and $2 are captured via the brackets $values{$current_host}{$1} = $2; } } #for debug: print Dumper \%values; #to print a specific key: my $target_key = "hl:load_avg"; foreach my $host ( sort keys %values ) { print "$host - $target_key=",$values{$host}{$target_key},"\n"; }