Eliminați linia care conține anumite șiruri și următoarea linie

Eu folosesc acest lucru

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

pentru a elimina liniile care conțin șirul bar din fișier.

Aș dori totuși să elimin aceste linii și linia direct după el . De preferință în sed, awk sau în alt instrument disponibil în MinGW32.

Este un fel de inversare despre ceea ce pot obține în grep cu -A și -B pentru a imprima și liniile potrivite ca linii înainte / după linia potrivită.

Există vreo modalitate ușoară de a o atinge?

Comentarii

  • Doar pentru informație: Am ‘ m analizând jurnalele în care intrările sunt cu două linii. Așa că vreau să găsesc o intrare care să se potrivească cu modelul și să o elimin, precum și linia următoare. Prin urmare, nu ‘ nu trebuie să gestionez liniile de potrivire consecutive, dar mulțumesc oricum pentru integralitatea răspunsurilor dvs.!

Răspuns

Dacă aveți GNU sed (deci Linux sau Cygwin neîncorporat):

sed "/bar/,+1 d" 

Dacă aveți au bar pe două linii consecutive, aceasta va șterge a doua linie fără a o analiza. De exemplu, dacă aveți un fișier cu 3 linii bar / bar / foo, linia foo va rămâne.

Comentarii

  • +1 pentru lungime 🙂 În special exemplu nu ‘ nu am bar consecutive, așa că acesta este foarte ușor de reținut.
  • sed '/bar/d' dacă doriți doar să ” Eliminați linia care conține anumite șiruri ” și nu următorul.
  • Dacă vreau să elimin toate liniile după matematică, atunci?
  • @Pandya Acest lucru diferă ‘. Puteți utiliza de ex. sed '/math/q'
  • @ A.K. Dacă doriți doar să ștergeți linia potrivită, ‘ este chiar mai simplu: sed '/bar/d'

Răspuns

Dacă bar poate apărea pe linii consecutive, ați putea face:

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

care poate fi adaptat pentru a șterge mai mult de 2 linii schimbând cele 2 de mai sus cu numărul de linii de șters, inclusiv cel care se potrivește.

Dacă nu, „se face ușor în sed cu soluția @MichaelRollins” sau:

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

Comentarii

  • Celălalt plus din soluția AWK este că pot înlocui /bar/ /bar|baz|whatever/. În sed această sintaxă nu pare să funcționeze ‘.
  • @ jakub.g, am sed GNU ( v4.4 acum). Nu sunt sigur de ceilalți. Ceea ce știu este că folosește în mod implicit ” de bază ” sintaxa expresiei regulate >

nu funcționează. Pentru a obține ceea ce doriți, puteți pune o bară inversă în fața fiecărei linii verticale sau puteți ceresedsă utilizați ” extins ” expresii regulate. Mai multe informații aici: gnu.org/software/sed/manual/html_node/… . Vă rugăm să rețineți că acest lucru este valabil și pentru

grep. Aici ‘ este propriul meu exemplu de lucru:echo $'0a\n1b\n2c' | sed '/0a\|1b/d'.

Răspuns

Nu cunosc flu sed, dar este ușor să o faci în awk:

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

The awk script citește: pentru o linie care conține bara, obțineți următoarea linie (getline), apoi săriți toate procesările ulterioare (următoarea). Modelul 1 de la sfârșit imprimă liniile rămase.

Actualizați

După cum sa subliniat în comentariu, soluția de mai sus nu a funcționat cu bar. Iată o soluție revizuită, care o ia în considerare:

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

Acum continuăm să citim pentru a sări peste toate / barul / liniile.

Comentarii

  • Pentru a reproduce grep -A 100%, trebuie să gestionați orice număr de liniile corect (prin eliminarea întregului bloc și 1 linie după).

Răspuns

Veți dori să utilizați capabilitățile de scriptare ale sedului pentru a realiza acest lucru.

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

Date eșantion:

$ cat sample1.txt foo bar biz baz buz 

Comanda „N” adaugă următoarea linie de intrare în spațiul modelului. Aceasta combinată cu linia din potrivirea modelului (/ bar /) vor fi liniile pe care doriți să le ștergeți. Puteți apoi ștergeți normal cu comanda „d”.

Comentarii

  • Cum introduc o linie nouă în consolă? Sau acesta este doar script?
  • @ jakub.g: cu GNU sed: sed -e '/bar/{N;d}' sample1.txt

Răspuns

Dacă orice linie imediat următoare unui meci ar trebui eliminată, atunci programul dvs. sed va trebui să ia în considerare meciuri consecutive. Cu alte cuvinte, dacă eliminați o linie după o potrivire care se potrivește și cu ea, atunci probabil că ar trebui să eliminați și linia care urmează.

Este implementat suficient de simplu – dar trebuie să vă uitați puțin în spate .

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  

Funcționează schimbând spațiile de așteptare și model pentru fiecare linie citită – astfel încât ultima linie să poată fi comparată cu curentul de fiecare dată. Deci, atunci când sed citește o linie, schimbă conținutul bufferelor sale – iar linia anterioară este conținutul bufferului de editare, în timp ce linia curentă este pusă în spațiul de așteptare.

Deci, sed verifică linia anterioară pentru o potrivire cu match și dacă ! nu a fost găsit cele două expresii din funcția { } sunt rulate. sed va g și spațiul de așteptare prin suprascrierea spațiului modelului – ceea ce înseamnă că linia curentă se află atât în spațiul de păstrare, cât și în spațiul modelului – și apoi // o va verifica pentru o potrivire cu cea mai recentă expresie regulată compilată – match – și dacă it nu match este p rinted.

Aceasta înseamnă că o linie este tipărită numai dacă nu match și linia imediat anterioară nu match . De asemenea, renunță la orice schimburi inutile pentru secvențe de match es.

Dacă doriți o versiune care ar putea renunța la un număr arbitrar de linii care apare după un match ar avea nevoie de ceva mai multă muncă:

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 

. ..înlocuiți 5 cu numărul de linii (inclusiv linia potrivită) pe care doriți să le eliminați …


1 2 3 4 12 13 14 21 

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *