Jeg har følgende detaljer fra forarbejdet forespørgsel:

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 vil kun gribe hl:load_avg=38.980000 med præfikset abax55@lp55cs008 det betyder, at output skal se ud som:

abax55@lp55cs008 - hl:load_avg=38.980000 

…. dette er kun for en maskine, der hedder cs008. og det samlede antal maskiner ville være 100+.

Foreslå to muligheder:

  1. til kun at gribe en bestemt maskine,
  2. til at gribe alle maskiner

Kommentarer

  • griber alle maskiner – hvad er navngivningskonventionen for alle maskiner? har de et fælles præfiks i deres navne?
  • abax55 @ lp55cs001 abax55 @ lp55cs002 abax55 @ lp55cs003 abax55 @ lp55cs004 …. så videre!
  • min eneste input til hele denne query skal være ' abax55 ', hvile alt skal gøres med shell
  • Dit spørgsmål er stadig uklart og skal det være grep? Hvis grepping for et enkelt tilfælde er let, skal du udskrive teksten før resultatet
  • Brug af grep rep -o "hl:load_avg=38.980000" machines | xargs -L 1 echo "abax55@lp55cs008 -" eller awk awk 'match($0,/hl:load_avg=38.980000/) { print "abax55@lp55cs008 - " substr($0,RSTART,RLENGTH) }' machines

Svar

Awk løsning:

1) til kun at gribe en bestemt maskine:

awk -v m="cs008" "/abax55@lp55cs[0-9]/ && $1 ~ m{ m_name=$1 } m_name && /hl:load_avg=/{ print m_name" - "$1; exit }" file 

Outputtet:

abax55@lp55cs008 - hl:load_avg=38.980000 

2) til grepping af alle maskiner:

awk "/abax55@lp55cs[0-9]/{ m_name=$1 } m_name && /hl:load_avg=/{ print m_name" - "$1; m_name=0 }" file 

Kommentarer

  • er det muligt at køre hele kommandoen på en enkelt linje?
  • @Nayak, uddyb dit spørgsmål, det lyder vagt
  • er det muligt at ' awk -vm = " cs008 " ' / abax55 @ lp55cs [0-9] / & & $ 1 ~ m {m_name = $ 1} awk -vm = " cs008 " ' / abax55 @ lp55cs [0-9] / & & $ 1 ~ m {m_name = $ 1} ' i en enkelt linje?
  • ja. dette kan køres alt på én linje. Udskift de nye linjer i det citerede awk-script med ; tegn. (en eller begge newline og ; kan bruges til at adskille udsagn i awk).
  • meget enkel løsning og runtime er lav …. meget tak

Svar

Til test har jeg indsat samme indhold i fil flere gange ved at ændre værtsnavne i fil

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 

kommando

 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 

output

abax55@lp55cs008-hl:load_avg=38.980000 abax55@lp55cs009-hl:load_avg=38.980000 abax55@lp55cs007-hl:load_avg=38.980000 

Kommentarer

  • @Nayak Kan du stemme på svar

Svar

Jeg ville ikke bruge grep Jeg ville bruge 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"} 

Jeg kan sandsynligvis forfine det, hvis du er i stand til at give et mere specifikt rekordformat. Men du kan let parse hele strofe i en blok, fordi hver nye “blok” ikke har noget mellemrum i starten (det er endnu lettere, hvis der er en klar afgrænsning mellem posterne, f.eks. En tom linje, men uden at se dit output kan jeg ikke fortælle hvad det ville væ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"; } 

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *