Làm thế nào để tìm các dòng khớp với một mẫu và xóa chúng?


14

Trong một tệp có nhiều dòng tôi muốn xóa các dòng bắt đầu bằng HERE IT IS.

Làm thế nào tôi có thể làm điều này bằng cách chỉ sử dụng các công cụ dòng lệnh?


2
Mặc dù có một chút khác thường, bạn có thể sử dụng vimnhư vậy : vim '+g/^HERE IT IS/d' +wq test.txt;)
Doorknob

@Doorknob, cảm ơn bạn đã chỉ ra điều này. Thật ra tôi đang trên đường sử dụng vim
micgeronimo

Câu trả lời:


28

Hãy thử sed:

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

CẢNH BÁO: Tốt hơn là nên sao lưu khi sử dụng -icông tắc sed:

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

Các tập tin ban đầu sẽ vẫn như <file>.bakvà tập tin sửa đổi sẽ được <file>.


Làm cách nào tôi có thể đặt ký tự dòng mới sau chuỗi khớp và ghi vào dòng mới?
micgeronimo

2
sed -i 's/^HERE IT IS/HERE IT IS\n/' <file>
heemayl

1
@micgeronimo: rất vui được giúp đỡ. Vui lòng kiểm tra chỉnh sửa của tôi.
heemayl

6
@micgeronimo cố gắng đặt câu hỏi mà bạn thực sự muốn trả lời trong câu hỏi ban đầu của bạn (hãy nhớ rằng bạn có thể chỉnh sửa nó), thay vì thông qua các nhận xét có thể bị xóa / xóa. Bạn có thể sử dụng sed '/^HERE IT IS/G' file.
Steeldo

1
Sử dụng sed là rất chuyên nghiệp.
LakshyaAg

18

Ngoài những câu trả lời hay grepsedbạn đã nhận được, đây là một số công cụ khác có thể làm điều tương tự:

  • Một vài cách 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
    

    Bạn có thể thêm công -itắc vào bất kỳ ví dụ nào để chỉnh sửa tệp tại chỗ:

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

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

    Các phiên bản mới hơn (4.1.1 trở lên) của GNU awk(mặc định awktrên Linux) cũng có thể chỉnh sửa tệp tại chỗ:

    gawk -i inplace  '!/^HERE IT IS/' file
    
  • Shell ( bash, zsh, ksh, có lẽ những người khác). Điều này là loại ngớ ngẩn, nó có thể được thực hiện nhưng các công cụ khác là tốt hơn.

    while IFS= read -r line; do 
      [[ $line =~ ^"HERE IT IS" ]] || printf "%s\n" "$line"
    done < file > newfile
    

1
Bạn chỉ đang thể hiện! ;-) (nhưng bạn có một upvote, vì nó thông minh và tôi đã học được rất nhiều và người bashđã biến tôi thành LOL)
Fabby

bash one nên sử dụng printf "%s\n" "$line": trích dẫn dòng $ để duy trì khoảng trắng và tránh một số vấn đề về tiếng vang (diễn giải các ký tự đặc biệt, v.v.). và tránh sự cần thiết phải thêm --quá.
Olivier Dulac

@OlivierDulac đủ công bằng. Tôi không muốn làm phức tạp mọi thứ cho các trường hợp bên lề nhưng vì Cuanglm đã thêm vào IFS=-r, tôi cũng có thể đi tất cả các cách và làm cho nó mạnh mẽ.
terdon

@terdon: tất cả là vì lợi ích tốt hơn ^^ (và tôi đã làm +1 rồi, vì nó rất hữu ích cho người mới bắt đầu)
Olivier Dulac

2
@OlivierDulac Tôi có thể đảm bảo với bạn rằng nếu tôi đăng bài trên Unix & Linux, tôi đã sử dụng printf, IFS =, -r và trích dẫn :). Tôi thường đơn giản hóa mọi thứ cho khán giả AU, những người thường không thoải mái với dòng lệnh.
terdon

13

Tôi sẽ sử dụng grepđể lọc chúng ra. Ví dụ :

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

Sau đó di chuyển outfile trở lại infile.


Suy nghĩ thông minh
Anwar

5

sed chắc chắn là con đường để đi

Điều chỉnh nhỏ này của lệnh @heemayl đã cho bạn sẽ xóa dòng cho dù trường hợp tương tự có được sử dụng trong mẫu hay không, do tham chiếu I trong mẫu.

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

Nếu bạn có một vài tệp trong một thư mục mà bạn muốn thực hiện điều này, bạn có thể kết hợp nó với tìm như vậy.

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

Tùy chọn maxdepth có nghĩa là điều này sẽ không tái diễn vào các thư mục.


4

Một tùy chọn trăn khác:

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

Trong đó f là đường dẫn đến tệp, giữa các dấu ngoặc kép.


4

Grep

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

(?!HERE IT IS)khẳng định cái nhìn tiêu cực làm cho công cụ regex khớp với tất cả các ranh giới bắt đầu dòng ( thường được khớp bởi^ ) chỉ khi nó không được theo sau bởi chuỗiHERE IT IS

trăn

#!/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="")

Lưu tập lệnh trong một tập tin, nói script.pyvà sau đó chạy nó thông qua lệnh dưới đây trên thiết bị đầu cuối.

python3 script.py infile

bạn có thể sử dụng regex ở đó, như thế [print(l, end = "") for l in open(fil).readlines() if not re.match("HERE IT IS", l)], nhưng nó không hiệu quả hơn nhiều startswith. Tôi tự hỏi làm thế nào [print(l, end = "") for l in open(f).readlines() if not l.startswith("HERE IT IS")]sẽ không tạo ra đầu ra trong một danh sách.
Avinash Raj

Lần đầu tiên tôi gặp nó, nó trông thật lạ. Nó tạo ra một lệnh in (hoặc bất kỳ hành động nào bạn muốn thực hiện với nó) cho tất cả các mục trong danh sách đã xác định.
Jacob Vlijm

Hoàn tác nó, chỉ để cho vui :)
Jacob Vlijm

1

Bạn có thể sử dụng Vim trong chế độ Ex:

ex -sc 'g/^HERE IT IS/d' -cx file
  1. g tìm kiếm toàn cầu

  2. d xóa bỏ

  3. x lưu và đóng

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.