Alla on tiedoston teksti:
Pseudo name=Apple Code=42B state=fault Pseudo name=Prance Code=43B state=good
Minun täytyy napata ”42B” ja hanki ulostulo yllä olevasta tekstistä, kuten:
Pseudo name=Apple Code=42B state=fault
Onko kukaan aavistustakaan tämän saavuttamiseksi käyttämällä grep
/ awk
/ sed
?
Kommentit
- Merkitsit tämän kysymyksen vain " grep " -merkillä. Etsitkö sitten vain " grep " -ratkaisuja? Määrität kysymyksessä myös awk & sed. Voimmeko lisätä nuo tunnisteet? En ollut ' varma aikomuksestasi, kun muokkain kysymystä viime yönä.
- stackoverflow.com/ kysymykset / 12024410 / …
vastaus
Kanssa awk
awk -v RS="" "/42B/" file
RS=
vaihtaa syötetietueen erotinta uudesta rivistä tyhjiin riveihin. Jos jokin tietueen kenttä sisältää /42B/
, tulosta tietue.
""
(tyhjä merkkijono) on taika arvo, jota käytetään edustamaan tyhjiä rivejä POSIXin mukaisesti:
Jos RS on tyhjä, sitten tietueet erotetaan sekvensseillä, jotka koostuvat
<newline>
plus yhdestä tai useammasta tyhjästä rivit, tyhjät rivit, jotka johtavat tai ovat perässä, eivät saa johtaa tyhjiin tietueisiin syötteen alussa tai lopussa, ja<newline>
on aina oltava kentän erotin, riippumatta siitä, minkä arvo FS on.
Lähtökappaleita ei erotettava, koska lähdönerotin on yksi uusi rivi. Varmista, että lähtökappaleiden välillä on tyhjä rivi, asettamalla lähtötietueiden erotin kahteen uuteen riviin:
awk -v RS="" -v ORS="\n\n" "/42B/" file
kommentit
- +1 tyylikkääseen ratkaisuun. Sinun <
ei kuitenkaan tarvitse ohjata tiedostoa uudelleen …
FILENAME
), se ' ei ole huono idea käyttää uudelleenohjausta, koska näin vältetään ongelmat tiedostonimessä =
tai alkaa -
(tai on -
), tekee johdonmukaiset virheilmoitukset ja välttää awk
: n suorittamista tai muiden uudelleenohjausten suorittamista, jos syötetiedosto voidaan ' avata. Vastaus
Olettaen, että tiedot on jäsennelty siten, että ne ovat aina haluamasi rivi ennen ja jälkeen, voit käyttää grep: n -A
(jälkeen) ja -B
(ennen) kytkimiä kertomaan, että siihen sisällytetään yksi rivi ennen ottelua ja yksi rivi sen jälkeen:
$ grep -A 1 -B 1 "42B" sample.txt Pseudo name=Apple Code=42B state=fault
Jos haluat samoja numerorivejä hakutermin edessä ja jälkeen, voit käyttää -C
(konteksti) -kytkintä:
$ grep -C 1 "42B" sample.txt Pseudo name=Apple Code=42B state=fault
Jos haluat olla tiukempi sovitettaessa useita rivejä, voit käyttää työkalua pcregrep
vastaamaan kuvio useilla viivoilla:
$ pcregrep -M "Pseudo.*\n.*42B.*\nstate.*" sample.txt Pseudo name=Apple Code=42B state=fault
Yllä oleva kuvio vastaa seuraavasti:
-
-M
– useita rivejä -
"Pseudo.*\n.*42B.*\nstate.*"
– vastaa merkkijonoryhmää, jossa ensimmäinen merkkijono alkaa sanalla"Pseudo"
, jota seuraa mitä tahansa merkkejä rivin loppuun\n
, jota seuraa kaikki merkit merkkijonoon"42B"
, jota seuraa kaikki merkit, kunnes toinen rivin pää (\n
), jota seuraa merkkijono"state"
ja kaikki merkit.
Kommentit
vastaus
grep
joillakin Unixin makuilla on -p
-merkki kappaleelle. Tiedän, että AIX tekee .
grep -p 42B <myfile>
tekisi juuri sen, mitä sinä siellä pyydät YMMV: llä ja GNU: n grepillä ei ole tätä lippua.
Kommentit
- P-lipun käyttäminen olisi ihanaa. Varsinkin jos sitä käytetään yhdessä -v: n kanssa, jotta voit sulkea kokonaiset kappaleet ulos tuotoksesta.
Vastaus
On todennäköisesti samalla tavoin helppo tapa tehdä se awk: llä, mutta perl:
cat file | perl -ne "BEGIN { $/="\n\n" }; print if $_ =~ /42B/;"
Siinä sanotaan periaatteessa, että tiedosto jaetaan tyhjiksi riveiksi rajatuiksi paloiksi ja tulostetaan sitten vain säännöllisen lausekkeenne vastaavat palat. Kommentit
Vastaa
Muu perl-ratkaisu, ilman tyhjän rivin lopussa:
perl -00ne "if ($_ =~ /42B/) {chomp($_); printf "%s\n",$_}" foo
esimerkki
% 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
Kommentit
- Tai lyhyempi (ja siten helppolukuisempi), kuten triplee kirjoitti kommentissa:
perl -00 -ne 'print if /42B/' file
.
-C
(konteksti) voidaan käyttää pikakuvakkeena, jos-A
ja-B
ovat samat.