Poista tietty merkkijono ja seuraava rivi sisältävä rivi

Käytän tätä

cat foo.txt | sed "/bar/d"

poistaa riviä, joka sisältää merkkijonon bar tiedostossa.

Haluan kuitenkin poistaa nämä rivit ja rivi suoraan sen jälkeen . Mieluiten sed, awk tai muussa työkalussa, joka on käytettävissä MinGW32: ssa.

Se on eräänlainen käänteinen siitä, mitä voin saada grep kanssa -A ja -B, jotta voin tulostaa myös vastaavat rivit rivinä ennen / jälkeen vastaavan rivin.

Onko olemassa helppo tapa saavuttaa se?

Kommentit

  • Vain tiedot: I ’ m analysoin lokeja, joissa merkinnät ovat kaksirivisiä. Joten haluan löytää merkinnän vastaavan merkinnän ja poistaa sen sekä seuraavan rivin. Siksi minun ei ’ tarvitse käsitellä peräkkäisiä ottelulinjoja, mutta kiitos vastausten täydellisyydestä!

Vastaa

Jos sinulla on GNU sed (joten sulautettu Linux tai Cygwin):

sed "/bar/,+1 d" 

Jos bar kahdella peräkkäisellä rivillä, tämä poistaa toisen rivin analysoimatta sitä. Esimerkiksi, jos sinulla on 3-rivinen tiedosto bar / bar / foo, foo -rivi pysyy.

Kommentit

  • +1 pituudelle 🙂 esimerkki Minulla ’ ei ole peräkkäisiä bar s, joten tämä on erittäin helppo muistaa.
  • sed '/bar/d' jos haluat vain ” poistaa tietyn merkkijonon sisältävän rivin ” ja ei seuraava.
  • Jos haluan poistaa kaikki rivit matematiikan jälkeen?
  • @Pandya Se on ’ erilainen. Voit käyttää esim. sed '/math/q'
  • @ A.K. Jos haluat vain poistaa vastaavan rivin, se ’ on vielä yksinkertaisempi: sed '/bar/d'

Vastaus

Jos bar saattaa esiintyä peräkkäisillä riveillä, voit tehdä seuraavaa:

awk "/bar/{n=2}; n {n--; next}; 1" < infile > outfile 

joka voidaan mukauttaa poistamaan enemmän kuin 2 riviä muuttamalla 2 yllä olevalla rivillä poistettavien rivien määrällä, mukaan lukien vastaava.

Jos ei, se ”s helppo tehdä sed ratkaisulla @MichaelRollins” tai:

sed "/bar/,/^/d" < infile > outfile 

Kommentit

  • AWK-ratkaisun toinen plus on, että voin korvata /bar/ /bar|baz|whatever/. Kohdassa sed tämä syntaksi ei näytä toimivan. Id id ”” 13eec19014 ”>

ei näytä toimivan.

  • @ jakub.g, minulla on GNU sed ( v4.4 nyt). Etkö ole varma muista. Tiedän, että se käyttää oletusarvoisesti ” basic ” säännöllisen lausekkeen syntaksia. Siksi esimerkkisi ei ’ ei toimi. Halutessasi voit joko laittaa taaksepäin viivan jokaisen pystyviivan eteen tai pyytää sed käyttämään ” laajennettu ” säännölliset lausekkeet. Lisätietoja täältä: gnu.org/software/sed/manual/html_node/… . Huomaa, että tämä koskee myös grep. Tässä ’ s oma toimiva esimerkkini: echo $'0a\n1b\n2c' | sed '/0a\|1b/d'.
  • Vastaa

    En puhu sujuvasti sedia, mutta se on helppo tehdä awk:

    awk "/bar/{getline;next} 1" foo.txt 

    awk-komentosarja lukee: riville, joka sisältää palkin, hanki seuraava rivi (getline) ja ohita sitten kaikki seuraava käsittely (seuraava). Lopussa oleva 1 kuvio tulostaa loput rivit.

    Päivitä

    Kuten kommentissa todettiin, yllä oleva ratkaisu ei toiminut peräkkäisten bar. Tässä on uudistettu ratkaisu, joka ottaa sen huomioon:

    awk "/bar/ {while (/bar/ && getline>0) ; next} 1" foo.txt 

    Jatkamme nyt lukemista ohittaaksesi kaikki / bar / rivit.

    Kommentit

    • Jos haluat toistaa grep -A 100%, sinun on myös käsiteltävä mitä tahansa määrää peräkkäisiä bar rivit oikein (poistamalla koko lohko ja yksi rivi sen jälkeen).

    Vastaa

    Tämän saavuttamiseksi sinun on käytettävä sedin komentosarjaominaisuuksia.

    $ sed -e "/bar/ { $!N d }" sample1.txt 

    Esimerkkitiedot:

    $ cat sample1.txt foo bar biz baz buz 

    Komento ”N” liittää seuraavan syöttörivin kuviotilaan. Tämä yhdistettynä mallivastauksen / / bar /) riviin on rivit, jotka haluat poistaa. Voit sitten poista normaalisti komennolla ”d”.

    Kommentit

    • Kuinka kirjoitan uuden rivin konsoliin? Tai tämä on vain komentosarja?
    • @ jakub.g: GNU: n kanssa sed: sed -e '/bar/{N;d}' sample1.txt

    Vastaus

    Jos jokin välittömästi ottelun jälkeen oleva rivi on poistettava, sed -ohjelman on otettava huomioon peräkkäiset ottelut. Toisin sanoen, jos poistat rivin myös vastaavan ottelun jälkeen, luultavasti sinun pitäisi poistaa myös sitä seuraava rivi.

    Se toteutetaan yksinkertaisesti – mutta sinun on katsottava hieman taaksepäin .

    printf %s\\n 0 match 2 match match \ 5 6 match match match \ 10 11 12 match 14 15 | sed -ne"x;/match/!{g;//!p;}" 

     0 6 11 12 15  

    Se toimii vaihtamalla pito- ja kuviotilat jokaiselle luetulle riville – joten viimeistä riviä voidaan verrata joka kertaan nykyiseen. Joten kun sed lukee rivin, se vaihtaa puskuriensa sisällön – ja edellinen rivi on sen muokkauspuskurin sisältö, kun taas nykyinen rivi asetetaan pitotilaan.

    Joten sed tarkistaa edellisen rivin vastaavuuden match ja jos sen ! ei löytänyt kahta lauseketta funktiossa { } suoritetaan. sed g et pitää pitotilan korvaamalla kuviotilan – mikä tarkoittaa, että nykyinen viiva on tällöin sekä pidossa että kuvioissa – ja sitten // tarkistaa sen vastaavuuden viimeksi koottuun säännölliseen lausekkeeseensa – match – ja jos se ei match , se on p rinted.

    Tämä tarkoittaa, että rivi tulostetaan vain, jos se ei match ja välittömästi edellinen rivi ei match . Se myös hylkää kaikki tarpeettomat vaihdot match es -sekvensseille.

    Jos haluat version, joka voi pudottaa mielivaltaisen määrän rivejä match : n jälkeen se tarvitsee hieman enemmän työtä:

    printf %s\\n 1 2 3 4 match \ match match 8 \ 9 10 11 12 13 \ 14 match match \ 17 18 19 20 21 | sed -net -e"/match/{h;n;//h;//!H;G;s/\n/&/5;D;}" -ep 

    . ..korvaa 5 rivien lukumäärällä (mukaan lukien vastaava viiva) , jonka haluat poistaa …


    1 2 3 4 12 13 14 21 

    Vastaa

    Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *