Mam następujące szczegóły przetworzonego zapytania:
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 chcę tylko grep hl:load_avg=38.980000
z prefiksem abax55@lp55cs008
, co oznacza, że wynik powinien wyglądać następująco:
abax55@lp55cs008 - hl:load_avg=38.980000
…. to jest tylko dla jednego komputera o nazwie cs008
. a łączna liczba maszyn to ponad 100.
Zaproponuj 2 opcje:
- do grepowania tylko określonej maszyny,
- do grepowania wszystkich maszyny
Komentarze
Odpowiedź
Awk
rozwiązanie:
1) do grepowania tylko określonej maszyny:
awk -v m="cs008" "/abax55@lp55cs[0-9]/ && $1 ~ m{ m_name=$1 } m_name && /hl:load_avg=/{ print m_name" - "$1; exit }" file
Wynik:
abax55@lp55cs008 - hl:load_avg=38.980000
2) do grepowania wszystkich komputerów:
awk "/abax55@lp55cs[0-9]/{ m_name=$1 } m_name && /hl:load_avg=/{ print m_name" - "$1; m_name=0 }" file
Komentarze
- czy można uruchomić całe polecenie w jednej linii?
- @Nayak, doprecyzuj swoje pytanie, brzmi niejasne
- czy można ' awk -vm = " cs008 " ' / abax55 @ lp55cs [0-9] / & & $ 1 ~ m {m_name = $ 1} awk -vm = " cs008 " ' / abax55 @ lp55cs [0-9] / & & $ 1 ~ m {m_name = $ 1} ' w jednej linii?
- tak. można to uruchomić w jednym wierszu. Zastąp znaki nowej linii w cytowanym skrypcie awk
;
znakami. (do oddzielenia instrukcji wawk
można użyć zarówno nowej linii, jak i;
). - bardzo proste rozwiązanie a czas wykonania jest niski … dziękuję bardzo
Odpowiedź
W celu testowania wstawiłem tę samą treść w pliku wiele razy, zmieniając nazwy hostów w pliku
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
polecenie
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
wyjście
abax55@lp55cs008-hl:load_avg=38.980000 abax55@lp55cs009-hl:load_avg=38.980000 abax55@lp55cs007-hl:load_avg=38.980000
Komentarze
- @Nayak Czy możesz głosować na odpowiedź
Odpowiedź
Nie użyłbym grep
Użyłbym perl
:
#!/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"}
Prawdopodobnie mogę to udoskonalić, jeśli „jesteś w stanie podać bardziej szczegółowy format rekordu. Ale możesz dość łatwo przeanalizować całą strofę w blok, ponieważ każdy nowy „blok” nie ma spacji na początku (jest to jeszcze łatwiejsze, jeśli istnieje wyraźny separator między rekordami, taki jak pusty wiersz, ale bez widoczności nie mogę powiedzieć, co to będzie).
#!/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"; }
rep -o "hl:load_avg=38.980000" machines | xargs -L 1 echo "abax55@lp55cs008 -"
lub awkawk 'match($0,/hl:load_avg=38.980000/) { print "abax55@lp55cs008 - " substr($0,RSTART,RLENGTH) }' machines