Làm thế nào để lệnh sed '1! G; h; $! D' đảo ngược nội dung của một tệp?


20

Câu hỏi của tôi liên quan đến sedgiải pháp cụ thể được đưa ra trong câu trả lời này cho câu hỏi này về chế độ đảo ngược . Các sed/ grepgiải pháp mà tôi không thể giải mã được những điều sau một:

sed '1!G;h;$!d' file

Ai đó có thể vui lòng giải mã lệnh này?

Tôi biết từ kiến ​​thức VI (M) rằng G biểu thị dòng cuối cùng của tệp và trong sed a bang (!) Theo sau là một địa chỉ hoạt động hơi giống như grep -vvậy để nói rằng nó sẽ không khớp với dòng đó. Nhưng như một toàn bộ kịch bản sed nội tuyến ở trên là ngoài tôi.


3
... rất chậm ...
mikeerv

1
Như gợi ý mikeerv. Bạn nên lưu ý rằng sedcông thức phức tạp này là một cách cực kỳ kém hiệu quả (độ phức tạp O (n ^ 2/2)) để đảo ngược các dòng trong một tệp. Sẽ rất chậm đối với các tệp có số lượng dòng lớn. Để biết cách thay thế đảo ngược thứ tự dòng hiệu quả hơn nhiều, hãy xem tactừ lõi core GNU.
thân

Câu trả lời:


35

Điều này đảo ngược dòng tập tin theo dòng.

sed '1 G;! h;! $ d' tập tin

Đầu tiên, sedcó một không gian giữ và một không gian mô hình . Chúng ta phải phân biệt giữa chúng trước khi tập trung vào lệnh cụ thể đó.

Khi sedđọc một dòng mới, nó được tải vào không gian mẫu. Do đó, không gian đó được ghi đè mỗi khi một dòng mới được xử lý. Mặt khác, không gian giữ nhất quán trong toàn bộ quá trình xử lý và các giá trị có thể được lưu trữ ở đó để sử dụng sau này.


Theo lệnh:

Có 3 lệnh trong bản Tuyên Bố này: 1!G, h$!d

  • 1!Gcó nghĩa là Glệnh được thực thi trên mỗi dòng trừ dòng đầu tiên ( !phủ định 1). Gcó nghĩa là nối thêm những gì trong không gian giữ vào không gian mẫu.

  • háp dụng cho mọi dòng. Nó sao chép không gian mẫu vào không gian giữ (và ghi đè lên nó).

  • $!dáp dụng cho mọi dòng trừ dòng cuối cùng ( $đại diện cho dòng cuối cùng, !phủ nhận nó). dlà lệnh xóa dòng (không gian mẫu).


  1. Bây giờ, khi dòng đầu tiên được đọc, sedthực thi hlệnh. Dòng đầu tiên được sao chép vào không gian giữ. Sau đó, nó sẽ bị xóa, vì nó phù hợp với $!điều kiện. sedtiếp tục với dòng thứ hai.
  2. Dòng thứ hai khớp với điều kiện 1!(không phải là dòng đầu tiên) và do đó, không gian giữ (có dòng đầu tiên) được thêm vào không gian mẫu (có dòng thứ hai). Sau đó, trong không gian mẫu, bây giờ có dòng thứ hai theo sau là dòng đầu tiên, được phân định bởi một dòng mới. Bây giờ, hlệnh áp dụng (như trong mỗi dòng); tất cả những gì trong không gian mẫu được sao chép vào không gian giữ. Câu lệnh thứ ba ( $!d) được áp dụng: Dòng bị xóa khỏi không gian mẫu.
  3. Bước 2 bây giờ được thực hiện với tất cả các dòng. Chúng tôi bỏ qua đến dòng cuối cùng.
  4. Trong dòng cuối cùng ( $) gần như tất cả Bước 2 đã hoàn thành, nhưng không phải là phần xóa ( d). sed, khi được gọi mà không có -n, sẽ tự động in không gian mẫu ở cuối quá trình xử lý cho mỗi dòng đầu vào. Vì vậy, khi không bị xóa, không gian mẫu được in. Nó chứa tất cả các dòng theo thứ tự đảo ngược .

1
@Geek Không, hlệnh sao chép không gian mẫu vào không gian giữ, duy trì cho đến khi sedkết thúc. Sau khi kết thúc tập lệnh, mọi thứ sẽ bị xóa, vì nhị phân đã thoát.
hỗn loạn

2
Chúng ta có thể nghĩ về không gian giữ như các thanh ghi cho vim không? Họ cũng được đánh số? Hay chỉ có một trong số họ?
Geek

2
@Geek Trong sedchỉ có một không gian giữ. Nó giống như một biến có thể chứa thứ gì đó.
hỗn loạn

1
@ user1717828 Nếu chúng tôi không in dòng đầu tiên, khi được xử lý. Vì sed không được gọi với -nchúng tôi phải xóa mọi dòng trừ dòng cuối cùng. Ở dòng cuối cùng sed nối mọi thứ từ không gian giữ vào không gian mẫu. Và bởi vì dlệnh sẽ không được thực thi, dòng được in (dòng này chứa toàn bộ tệp bị đảo ngược).
hỗn loạn

1
(1) Câu hỏi / quan sát phụ của OP (trong phần bình luận) là, vì vậy hlệnh trên dòng cuối cùng là một loại không có ý nghĩa (có thêm điểm nhấn và hơi bị diễn giải). Anh ấy đúng; khi sedđang xử lý dòng đầu vào cuối cùng , sẽ Gđọc không gian giữ (để nối nó vào không gian mẫu) và sau đó hsao chép không gian mẫu vào không gian giữ, không bao giờ được tham chiếu lại . Chúng tôi cũng có thể nói sed 'G;$!h;$!d'hay sed 'G;$!{h;d}'. (2) Chúng ta có thể tránh sử dụng bằng dcách nói sed -n 'G;h;$p'.
Scott
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.