Nedan är texten i filen:

Pseudo name=Apple Code=42B state=fault Pseudo name=Prance Code=43B state=good 

Jag behöver grep för ”42B” och få utdata från ovanstående text som:

Pseudo name=Apple Code=42B state=fault 

Har någon idé om hur man uppnår detta med grep / awk / sed?

Kommentarer

  • Du taggade den här frågan med bara " grep ". Letar du bara efter " grep " lösningar då? I frågan anger du awk & sed också. Kan vi lägga till dessa taggar? Jag var inte ' inte säker på din avsikt när jag redigerade frågan igår kväll.
  • stackoverflow.com/ frågor / 12024410 / …

Svar

Med awk

awk -v RS="" "/42B/" file 

RS= ändras ingångspostseparatorn från en ny rad till tomma rader. Om något fält i en post innehåller /42B/ skriv ut posten.

"" (nullsträngen) är en magi värde som används för att representera tomma rader enligt POSIX :

Om RS är noll, sedan separeras poster med sekvenser som består av en <newline> plus en eller flera tomma rader, ledande eller efterföljande tomma rader får inte leda till tomma poster i början eller slutet av inmatningen, och en <newline> ska alltid vara en fältseparator, oavsett värdet på FS är.

Utgångsstyckena kommer inte separeras eftersom utmatningsseparatorn förblir en enda ny rad. För att säkerställa att det finns en tom rad mellan utgångsstycken ställer du in utgångspostavgränsaren på två nya rader:

awk -v RS="" -v ORS="\n\n" "/42B/" file 

Kommentarer

  • +1 för en elegant lösning. Du behöver dock inte ' omdirigera filen …
  • fingrarna var på autopiloten.
  • @jasonwryan, såvida du inte behöver åtkomst till filnamnet inom awk (FILENAME), det ' är inte en dålig idé att använda omdirigering eftersom det undviker problem för filnamn som innehåller = eller börjar med - (eller är -), ger konsekventa felmeddelanden och undviker att köra awk eller utföra andra omdirigeringar om ingångsfilen ' inte kan öppnas.

Svar

Förutsatt att data är strukturerade så att det alltid är raden före och efter det du vill kan du använda grep ”s -A (efter) och -B (före) växlar för att säga att den ska inkludera 1 rad före matchen och 1 rad efter den:

$ grep -A 1 -B 1 "42B" sample.txt Pseudo name=Apple Code=42B state=fault 

Om du vill ha samma antal rader före och efter söktermen kan du använda -C (context) -omkopplaren:

$ grep -C 1 "42B" sample.txt Pseudo name=Apple Code=42B state=fault 

Om du vill vara strängare när du matchar flera rader kan du använda verktyget pcregrep , för att matcha en mönster över flera rader:

$ pcregrep -M "Pseudo.*\n.*42B.*\nstate.*" sample.txt Pseudo name=Apple Code=42B state=fault 

Mönstret ovan matchar enligt följande:

  • -M – flera rader
  • "Pseudo.*\n.*42B.*\nstate.*" – matchar en grupp strängar där den första strängen börjar med ordet "Pseudo" följt av alla tecken fram till slutet av raden \n, följt av alla tecken upp till strängen "42B" följt av några tecken fram till en annan ände av raden (\n), följt av strängen "state" följt av alla tecken.

Kommentarer

  • -C (context) kan användas som en genväg, om -A och -B är desamma.
  • @DavidBaggerman – tack. Lade till det i svaret.
  • Varför den nedre rösten? Detta svarar på frågan.

Svar

grep vissa Unix-smaker har -p -flaggan för ”avsnitt”. Jag vet att AIX gör .

grep -p 42B <myfile> 

skulle göra precis vad du ber om där YMMV och GNU grep har inte den här flaggan.

Kommentarer

  • Att ha flaggan -p skulle vara underbart. Speciellt om de används tillsammans med -v så kan du utesluta hela stycken från utdata.

Svar

Det finns förmodligen ett liknande enkelt sätt att göra det med awk, men i perl:

cat file | perl -ne "BEGIN { $/="\n\n" }; print if $_ =~ /42B/;" 

Det säger i princip att dela upp filen i bitar avgränsade med tomma rader, för att bara skriva ut de bitar som matchar ditt vanliga uttryck.

Kommentarer

Svar

En annan perl-lösning, utan en tom rad:

perl -00ne "if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}" foo 

Exempel

% perl -00ne "if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}" foo Pseudo name=Apple Code=42B state=fault % cat foo Pseudo name=Apple Code=42B state=fault Pseudo name=Prance Code=43B state=good 

Kommentarer

  • Eller kortare (och därmed mer läsbar), som triplee skrev i en kommentar: perl -00 -ne 'print if /42B/' file.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *