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:

  1. do grepowania tylko określonej maszyny,
  2. do grepowania wszystkich maszyny

Komentarze

  • grepowanie wszystkich maszyn – jaka jest konwencja nazewnictwa dla wszystkich maszyn? czy mają wspólny prefiks w swoich nazwach?
  • abax55 @ lp55cs001 abax55 @ lp55cs002 abax55 @ lp55cs003 abax55 @ lp55cs004 …. tak dalej!
  • moje jedyne dane wejściowe dla tego całego zapytania powinno być ' abax55 ', reszta wszystko musi być zrobione przez powłokę
  • Twoje pytanie jest nadal niejasne i musi to będzie grep? Jeśli w jednym przypadku grepowanie jest łatwe, wydrukuj ten tekst przed wynikiem
  • Używając grep rep -o "hl:load_avg=38.980000" machines | xargs -L 1 echo "abax55@lp55cs008 -" lub awk awk 'match($0,/hl:load_avg=38.980000/) { print "abax55@lp55cs008 - " substr($0,RSTART,RLENGTH) }' machines

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 w awk 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"; } 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *