Nedenfor er teksten i filen:

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

Jeg må grep for «42B» og få utdata fra teksten ovenfor som:

Pseudo name=Apple Code=42B state=fault 

Er det noen som har ideer om hvordan du kan oppnå dette ved hjelp av grep / awk / sed?

Kommentarer

  • Du merket dette spørsmålet med bare " grep ". Leter du bare etter " grep " løsninger da? I spørsmålet angir du awk & sed også. Kan vi legge til disse kodene? Jeg var ikke ' ikke sikker på intensjonen din da jeg redigerte spørsmålet i går kveld.
  • stackoverflow.com/ spørsmål / 12024410 / …

Svar

Med awk

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

RS= endres separatoren for inngangspost fra en ny linje til tomme linjer. Hvis et felt i en post inneholder /42B/ skriv ut posten.

"" (nullstrengen) er en magi verdi brukt til å representere blanke linjer i henhold til POSIX :

Hvis RS er null, deretter skilles poster med sekvenser som består av en <newline> pluss ett eller flere blanke linjer, ledende eller etterfølgende tomme linjer skal ikke resultere i tomme poster i begynnelsen eller slutten av inngangen, og en <newline> skal alltid være en feltseparator, uansett hvilken verdi FS er.

Utgangsparagrafene vil ikke separeres siden utgangsseparatoren forblir en enkelt ny linje. For å sikre at det er en tom linje mellom utgangsparagrafene, sett utskillingsutskilleren til to nye linjer:

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

Kommentarer

  • +1 for en elegant løsning. Du trenger ikke ' ikke å omdirigere filen skjønt …
  • fingrene var på autopiloten.
  • @jasonwryan, med mindre du trenger tilgang til filnavnet i awk (FILENAME), er det ' ikke en dårlig idé å bruke omdirigering, da det unngår problemer for filnavn som inneholder = eller starter med - (eller er -), gir konsekvente feilmeldinger, og unngår å kjøre awk eller utføre andre omdirigeringer hvis inndatafilen ikke kan ' ikke åpnes.

Svar

Forutsatt at dataene er strukturert slik at det alltid er linjen før og etter det du vil, kan du bruke grep «s -A (etter) og -B (før) bytter for å fortelle den å inkludere 1 linje før kampen og 1 linje etter den:

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

Hvis du vil ha samme tallinjer før og etter søkeordet, kan du bruke -C (kontekst) -bryteren:

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

Hvis du «vil være strengere når du samsvarer med flere linjer, kan du bruke verktøyet pcregrep , for å matche en mønster over flere linjer:

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

Ovennevnte mønster samsvarer med følgende:

  • -M – flere linjer
  • "Pseudo.*\n.*42B.*\nstate.*" – samsvarer med en gruppe strenger der den første strengen starter med ordet "Pseudo" etterfulgt av eventuelle tegn frem til slutten av linjen \n, etterfulgt av alle tegn opp til strengen "42B" etterfulgt av eventuelle tegn frem til en annen ende av linjen (\n), etterfulgt av strengen "state" etterfulgt av eventuelle tegn.

Kommentarer

  • -C (kontekst) kan brukes som en snarvei, hvis -A og -B er de samme.
  • @ DavidBaggerman – takk. La det til i svaret.
  • Hvorfor stemmer den ene ned? Dette svarer på spørsmålet.

Svar

grep av noen smaker av Unix har -p flagget for «avsnitt». Jeg vet at AIX gjør .

grep -p 42B <myfile> 

ville gjort akkurat det du ber om der YMMV og GNU grep har ikke dette flagget.

Kommentarer

  • Å ha -p-flagget ville være fantastisk. Spesielt hvis det brukes sammen med -v, slik at du kan ekskludere hele avsnitt fra utdata.

Svar

Det er sannsynligvis en like enkel måte å gjøre det med awk, men i perl:

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

Som i utgangspunktet sier å dele filen i biter avgrenset av blanke linjer, og deretter bare skrive ut de biter som samsvarer med ditt vanlige uttrykk.

Kommentarer

  • Dette kan forenkles ved å bruke alternativer og stenografi, og miste unyttig bruk av cat ; perl -00 -ne 'print if /42B/' file

Svar

En annen perl-løsning, uten etterfølgende tom linje:

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

Eksempel

% 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 kortere (og dermed mer lesbar), som triplee skrev i en kommentar: perl -00 -ne 'print if /42B/' file.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *