Bagaimana menemukan garis yang cocok dengan suatu pola dan menghapusnya?

14

Dalam file dengan banyak baris saya ingin menghapus baris yang dimulai dengan HERE IT IS.

Bagaimana saya bisa melakukan ini hanya dengan menggunakan alat baris perintah?

micgeronimo
sumber
2
Meskipun sedikit tidak konvensional, Anda dapat menggunakan vimseperti vim '+g/^HERE IT IS/d' +wq test.txt
:;
@ Doorknob, terima kasih telah menunjukkan ini. Sebenarnya saya sedang dalam perjalanan untuk menggunakan vim
micgeronimo

Jawaban:

28

Coba sed:

sed -i '/^HERE IT IS/d' <file>

PERINGATAN: Lebih baik mengambil cadangan saat menggunakan -isakelar sed:

sed -i.bak '/^HERE IT IS/d' <file>

File asli akan tetap <file>.bakdan file yang diubah akan <file>.

heemayl
sumber
Bagaimana saya bisa menempatkan karakter baris baru setelah string yang cocok dan menulis ke baris baru?
micgeronimo
2
sed -i 's/^HERE IT IS/HERE IT IS\n/' <file>
heemayl
1
@ micgeronimo: senang membantu. Tolong periksa suntingan saya.
heemayl
6
@ micgeronimo mencoba untuk mengajukan pertanyaan yang Anda benar-benar ingin dijawab dalam pertanyaan awal Anda (ingat Anda dapat mengeditnya), daripada melalui komentar yang mungkin dibersihkan / dihapus. Anda bisa menggunakannya sed '/^HERE IT IS/G' file.
steeldriver
1
Penggunaan sed sangat pro.
LakshyaAg
18

Selain jawaban yang sangat bagus grepdan yang sedAnda terima, berikut adalah beberapa alat lain yang dapat melakukan hal yang sama:

  • Beberapa cara Perl:

    perl -ne '/^HERE IT IS/ || print' file > newfile
    perl -ne 'print if !/^HERE IT IS/' file > newfile
    perl -ne 'print unless /^HERE IT IS/' file > newfile
    

    Anda dapat menambahkan -iperalihan ke salah satu contoh untuk mengedit file di tempat:

    perl -i.bak -ne '/^HERE IT IS/ || print' file        
    
  • (melongo

    awk '!/^HERE IT IS/' file > newfile
    

    Versi yang lebih baru (4.1.1 dan yang lebih baru) dari GNU awk(default awkpada Linux) juga dapat mengedit file di tempat:

    gawk -i inplace  '!/^HERE IT IS/' file
    
  • Shell ( bash, zsh, ksh, mungkin orang lain). Ini agak konyol, itu bisa dilakukan tetapi alat lain lebih baik.

    while IFS= read -r line; do 
      [[ $line =~ ^"HERE IT IS" ]] || printf "%s\n" "$line"
    done < file > newfile
    
terdon
sumber
1
Anda hanya pamer! ;-) (tapi Anda mendapat suara positif, karena pintar dan saya belajar banyak dan yang bashmembuat saya LOL)
Fabby
bash yang harus digunakan printf "%s\n" "$line": mengutip $ line untuk mempertahankan spasi putih, dan menghindari beberapa masalah gema (menafsirkan karakter khusus, dll). dan menghindari kebutuhan untuk menambahkan --juga.
Olivier Dulac
@OlivierDulac cukup adil. Saya tidak ingin menyulitkan hal-hal untuk kasus pinggiran tetapi karena Cuanglm telah menambahkan IFS=dan -r, saya mungkin juga berusaha keras dan membuatnya kuat.
terdon
@terdon: semuanya baik-baik saja ^^ (dan saya sudah memberi +1, karena ini sangat informatif untuk pemula)
Olivier Dulac
2
@OlivierDulac Saya dapat meyakinkan Anda bahwa jika saya memposting di Unix & Linux saya akan menggunakan printf, IFS =, -r dan mengutip :). Saya sering menyederhanakan hal-hal untuk audiens AU yang sering kurang nyaman dengan baris perintah.
terdon
13

Saya akan gunakan grepuntuk memfilternya. Sebagai contoh :

grep -v "^HERE IT IS" infile > outfile

Kemudian pindahkan file outfile kembali ke infile.

Ben Hills
sumber
Pemikiran cerdas
Anwar
5

sed jelas merupakan cara untuk pergi.

Ini sedikit modifikasi dari perintah @heemayl memberi Anda akan menghapus baris apakah kasus yang sama digunakan dalam pola atau tidak, karena I dalam referensi pola.

sed -i '/HERE IT IS/Id' <file>

Jika Anda memiliki beberapa file dalam direktori yang Anda inginkan, Anda dapat menggabungkannya dengan find seperti itu.

find . -maxdepth 1 -type f -exec sed -i.bak '/HERE IT IS/Id' {} +

Opsi maxdepth berarti ini tidak akan muncul kembali ke direktori.

Arronikal
sumber
4

Opsi python lain:

#!/usr/bin/env python3
[print(l, end = "") for l in open(f).readlines() if not l.startswith("HERE IT IS")]

Di mana f adalah path ke file, di antara tanda kutip.

Yakub Vlijm
sumber
4

Grep

grep -P '^(?!HERE IT IS)' file

(?!HERE IT IS)pernyataan lookahead negatif yang membuat mesin regex untuk mencocokkan semua garis batas mulai ( yang biasanya cocok dengan^ ) hanya jika tidak diikuti oleh stringHERE IT IS

ular sanca

#!/usr/bin/python3
import sys
fil = sys.argv[1]
with open(fil) as f:
    for line in f:
        if not line.startswith('HERE IT IS'):
            print(line, end="")

Simpan skrip dalam file, ucapkan script.pydan kemudian jalankan melalui perintah di bawah ini di terminal.

python3 script.py infile
Avinash Raj
sumber
Anda bisa menggunakan regex di sana, seperti [print(l, end = "") for l in open(fil).readlines() if not re.match("HERE IT IS", l)], tapi itu tidak jauh lebih efisien daripada startswith. Saya bertanya-tanya bagaimana [print(l, end = "") for l in open(f).readlines() if not l.startswith("HERE IT IS")]tidak akan menghasilkan output dalam daftar.
Avinash Raj
Pertama kali saya menabraknya, itu tampak aneh bagi saya. Ini menghasilkan perintah cetak (atau tindakan apa pun yang ingin Anda lakukan dengannya) untuk semua item dalam daftar yang ditentukan.
Jacob Vlijm
Membatalkan penghapusan, hanya untuk bersenang-senang :)
Jacob Vlijm
1

Anda dapat menggunakan Vim dalam mode Ex:

ex -sc 'g/^HERE IT IS/d' -cx file
  1. g pencarian global

  2. d menghapus

  3. x Simpan dan tutup

Steven Penny
sumber