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/
. Însed
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 ceresed
să 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