Đây là một ví dụ hoàn hảo về việc tại sao sed
là s tream ed itor, và sẽ không bao giờ thay thế sức mạnh của ex
để chỉnh sửa tập tin tại chỗ.
ex -c '/address *172.29.16.103/
?{?,/}/d
x' input
Lệnh này là một hình thức đơn giản hóa không mạnh mẽ như nó có thể, nhưng phục vụ cho việc minh họa.
Lệnh đầu tiên tìm regex được chỉ định và di chuyển con trỏ đến dòng đó.
Lệnh thứ hai bao gồm hai địa chỉ được phân tách bằng dấu phẩy, trên đó d
lệnh elete được chạy. ?{?
tìm kiếm ngược từ dòng hiện tại cho một dấu ngoặc nhọn mở và /}/
tìm kiếm chuyển tiếp từ dòng hiện tại cho một dấu ngoặc nhọn gần. Tất cả mọi thứ ở giữa sẽ bị xóa (theo chiều dọc, do đó, phần đầu của dòng dấu ngoặc nhọn mở cũng bị xóa).
x
lưu các thay đổi và lối thoát. Và input
tất nhiên là tên của tập tin.
Đối với đầu vào bạn đã đưa ra, lệnh này hoạt động chính xác như mong muốn.
Bây giờ, tôi đã đề cập đến điều này có thể được cải thiện đáng kể. Chúng ta sẽ bắt đầu với regex. Sự rõ ràng nhất ở đây là thời gian là ký tự đại diện; regex như đã cho cũng có thể phù hợp với "172329-16 103". Vì vậy, các khoảng thời gian phải được thoát với dấu gạch chéo ngược để chúng chỉ khớp với các khoảng thời gian theo nghĩa đen.
Tiếp theo là khoảng trắng. Tôi đặt hai dấu cách theo sau là dấu * (tôi có thể đã sử dụng \+
nhưng tôi không biết tính năng đó có bắt buộc trong POSIX không), nhưng nếu có các tab trong tệp thì sao? Giải pháp tốt nhất là sử dụng [[:space:]]
. (Điều này sẽ trông đẹp hơn nhiều với \+
; nếu có ai tìm thấy liệu đó có phải là POSIX không, vui lòng gửi bình luận.)
Cuối cùng, nếu regex không được tìm thấy trong tập tin thì sao? Chà, sau đó, tệp sẽ được mở để chỉnh sửa và lệnh "tìm kiếm" sẽ thất bại và thông báo lỗi sẽ được in và phần còn lại của các lệnh đã cho sẽ không được thực thi - bạn sẽ bị bỏ lại trong ex
trình chỉnh sửa để bạn có thể thay đổi bằng tay. Tuy nhiên, nếu bạn muốn tự động hóa các chỉnh sửa trong tập lệnh, bạn có thể muốn trình chỉnh sửa thoát nếu không cần thay đổi. Câu trả lời là sử dụng g
lệnh lobal, và cũng sử dụng -s
cờ để chặn bất kỳ đầu ra nào từ ex
:
ex -sc 'g/address[[:space:]][[:space:]]*172\.29\.16\.103/ ?{?,/}/d
x' input
Điều này không hoàn toàn tương đương với lệnh trước đó; nếu có nhiều hơn một khối dấu ngoặc nhọn có một đường khớp, lệnh toàn cục ở đây sẽ xóa tất cả. Đó có lẽ là những gì bạn muốn anyway.
Nếu bạn chỉ muốn xóa trận đấu đầu tiên, trong khi thoát mà không thay đổi tệp nếu không có kết quả khớp nào, bạn có thể sử dụng x
lệnh như một phần của đối số cho g
lệnh (để thoát tệp sau khi lệnh xóa đầu tiên được thực hiện) và ném một q!
lệnh ở phía dưới trong trường hợp g
lệnh không thực thi vì thiếu bất kỳ dòng khớp nào.
ex -sc 'g/address[[:space:]][[:space:]]*172\.29\.16\.103/ ?{?,/}/d | x
q!' input
Thành thật mà nói, các lệnh này làm cho quá trình trông phức tạp hơn nhiều so với thực tế; sự mạnh mẽ đến từ chi phí cực kỳ rõ ràng và dễ đọc của mã. Đó là một sự đánh đổi.
Tôi khuyên bạn nên chỉnh sửa một vài tệp tương tác ex
để có cảm nhận về nó. Bằng cách đó bạn có thể thấy những gì bạn đang làm. Một phiên chỉnh sửa như vậy ex
để thực hiện sửa lỗi này tương tác trông giống như thế này:
$ ex input
"input" 23L, 843C
Entering Ex mode. Type "visual" to go to Normal mode.
:/103
host_name ServerB_172.29.16.103
:?{?,/}/d # This deletes the current block
:$p # Print and move to last line
:-5,.p # Print some more lines to check result
notification_interval 120
notification_period 24x7
}
:?}?+,.d # Trim whitespace
}
:x # Save and exit
$
Các thông số kỹ thuật POSIX đểex
cung cấp đọc thêm.