Làm thế nào để tôi in tất cả trừ dòng thứ N đến dòng cuối cùng trong sed?


9
  • Tôi muốn làm phần bổ sung / "ngược lại" của

    sed 13q;d <file.txt
    

    Tổng quát hơn, có thể thực hiện loại bổ sung / nghịch đảo / ngược lại này sedkhông? Hay chỉ cho regexes?

  • Làm cách nào để in tất cả trừ dòng thứ ba đến cuối cùng?. Điều này có yêu cầu hai tacvà đếm về phía trước sedkhông? Hoặc có cách nào để sedtự đếm từ phía sau?

Câu trả lời:


12

Phần 1

Đơn giản chỉ cần dxóa dòng thứ 13:

sed '13d' <file.txt

Và một cách chung để làm phần bổ sung ở trên là:

sed '13!d' <file.txt

Phần 2

Bởi vì nó có thể được thực hiện:

sed -n ':a;${P;q};N;4,$D;ba' <file.txt

Lưu ý 4là nhiều hơn số bạn yêu cầu. Vì vậy, nếu bạn muốn dòng thứ 10 cuối cùng, điều này sẽ là 11.

Kiểm tra với seq:

$ seq 100 | sed -n ':a;${P;q};N;4,$D;ba'
98
$ 

Cố gắng giải thích

:a        # define label a
${        # match the last line
    P     # print the first line of the pattern space
    q     # quit
}
N         # match all lines: append the next line to the pattern
4,${      # match the range of lines 4 to the end of the file
    D     # delete the first line of the pattern space
}
ba        # match all lines: jump back to label a 

Bổ sung có giá trị của Glenn Jackman:

Đó là "chỉ dòng thứ N". Đây là "tất cả NHƯNG dòng thứ N":

sed -n ':a;${s/^[^\n]*\n//;p;q};N;4,${P;D};ba'

hoạt động với GNU sed, \nchuỗi có thể không hoạt động với các sed khác.


Tôi đã thử điều này với BSD sed (OSX) và thấy nó không hoạt động tốt ở dạng trên. Các vấn đề dường như là:

  1. ; Được sử dụng để phân tách các dòng dường như thường hoạt động, nhưng không hoạt động sau một nhãn
  2. BSD sed dường như yêu cầu ;sau lệnh cuối cùng trong {}nhóm lệnh một dòng , trong khi GNU sed thì không
  3. \nnói chung có thể được sử dụng trong biểu thức chính quy, nhưng dường như không nằm trong []biểu thức ngoặc. Vì vậy, để loại trừ các dòng mới, chúng ta có thể sử dụng một cái gì đó như [[:alnum:][:punct:][:graph:][:blank:]]thay vào đó, mặc dù điều này có thể loại trừ các ký tự khác (cụ thể là các ký tự điều khiển khác).

Vì vậy, đây là một nỗ lực tại một phiên bản độc lập với nhiều nền tảng hơn:

sed -n ':a
${s/^[[:alnum:][:punct:][:graph:][:blank:]]*\n//p;q;};N;4,${P;D;};ba'

Điều này dường như hoạt động theo OSX và Ubuntu.


@jimmij Các câu trả lời khác về các câu hỏi liên quan trong mạng SE cho thấy rằng một head/ tailgiải pháp chậm hơn nhiều so với sedgiải pháp. Cảm ơn mặc dù.
đẳng cấu

3
@isomorphismes không có chương trình nào có thể biết số lượng dòng trong một tệp trừ khi nó đi qua toàn bộ tệp. Không có cách nào khác. Cách duy nhất để đếm từ dưới lên là đảo ngược tệp và đếm từ trên xuống hoặc phân tích cú pháp hai lần. Vì vậy, đầu / đuôi sẽ được khá nhanh như nó được.
terdon

@isomorphismes ... bởi vì họ ( head/ tail) được tối ưu hóa để làm những gì họ làm.
peterph

@isomorphismes - được chỉnh sửa với tất cả các phần bạn cần
Chấn thương kỹ thuật số

Đẹp! Tôi đã phải thay đổi câu trả lời của mình, vì bằng cách nào đó tôi dự đoán nó sẽ phức tạp hơn. :)
peterph
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.