Cara mencetak garis jika garis itu atau baris berikutnya tidak mengandung string tertentu

8

Input.txt:

    8B0C
    remove
    8B0D
    remove
    8B0E
    remove
    8B0F
    8B10
    remove
    8B14
    remove
    8B15
    remove
    8B16
    remove
    8B17
    remove
    8AC0
    8AC1
    remove
    8AC2
    remove
    8AC3
    remove
    8AE4
    8AE5
    8AE6
    remove

Output yang diinginkan:

    8B0F
    8AC0
    8AE4
    8AE5

Saya ingin mencetak baris jika baris itu atau baris berikutnya tidak mengandung 'hapus'. Saya menggunakan solaris 5.10, KSH.

ayrton_senna
sumber
@don_crissti Terima kasih, saya dapat menandai pertanyaan ini sebagai dijawab jika Anda mengirim jawaban Anda alih-alih berkomentar.
ayrton_senna

Jawaban:

14

Dengan sed:

sed '$!N;/remove/!P;D' infile

Ini menarik Ngaris ext ke dalam ruang pola (jika tidak !pada $garis t) dan memeriksa apakah ruang pola cocok remove. Jika tidak (berarti tidak ada satu pun dari dua garis dalam ruang pola yang berisi string remove), maka akan Pterputus ke \nkarakter ewline pertama (yaitu mencetak baris pertama). Kemudian Dmenghapus hingga \nkarakter baris pertama dan memulai ulang siklus. Dengan cara ini, tidak ada lebih dari dua garis dalam ruang pola.


Itu mungkin lebih mudah untuk memahami N, P, Dsiklus jika Anda menambahkan lsebelum dan setelah Nmelihat ruang pola:

sed 'l;$!N;l;/remove/!P;D' infile

jadi, gunakan hanya enam baris terakhir dari contoh Anda:

    8AC3
    remove
    8AE4
    8AE5
    8AE6
    remove

output perintah terakhir:

    8AC3 $
    8AC3 \ n hapus $
    hapus $
    hapus \ n 8AE4 $
    8AE4 $
    8AE4 \ n 8AE5 $
    8AE4
    8AE5 $
    8AE5 \ n 8AE6 $
    8AE5
    8AE6 $
    8AE6 \ n hapus $
    hapus $
    hapus $

Berikut ini penjelasan singkatnya:

cmd output cmd
l     8AC3$                  N # read in the next line
l     8AC3\n    remove$      D # delete up to \n (pattern space matches so no P)
l     remove$                N # read in the next line
l     remove\n    8AE4$      D # delete up to \n (pattern space matches so no P)
l     8AE4$                  N # read in the next line
l     8AE4\n    8AE5$        # pattern space doesn't match so print up to \n
P     8AE4                   D # delete up to \n
l     8AE5$                  N # read in the next line
l     8AE5\n    8AE6$        # pattern space doesn't match so print up to \n
P     8AE5                   D # delete up to \n 
l     8AE6$                  N # read in the next line
l     8AE6\n    remove$      D # delete up to \n (pattern space matches so no P)
l     remove$                # last line so no N 
l     remove$                D # delete (pattern space matches so no P)
don_crissti
sumber
5
awk '
    !/remove/ && NR > 1 && prev !~ /remove/ {print prev} 
    {prev = $0} 
    END {if (!/remove/) print}
' Input.txt 
glenn jackman
sumber
2
gawk 'BEGIN{ RS="remove\n"; ORS="" }
      RT{ print gensub("[^\n]*\n$","","") }; !RT{ print }' file

Metode di atas tidak membaca Records baris demi baris , melainkan membaca Catatan multi-line dari satu Pemisah Rekaman (RS) ke yang berikutnya (atau akhir file) - RSmenjadi baris "hapus" itu sendiri (termasuk membuntuti `\ n).

The !RTuji dibutuhkan ketika baris terakhir bukan merupakan RSline.
RT, gawk-isme , adalah teks aktual dari catatan saat ini RS.
gensubjuga merupakan gawk-isme .

Jika Anda perlu memeriksa garis penanda yang cocok dengan "hapus" di mana saja di dalam garis tersebut, vs garis yang sama dengan "hapus", maka cukup ganti Pemisah Catatan ke:

`RS="[^\n]*remove[^\n]*\n"`  

Keluaran:

8B0F
8AC0
8AE4
8AE5
Peter.O
sumber