Câu hỏi Lệnh thay thế 'sed' này có nhiều dấu @ hoạt động như thế nào?


Bất cứ ai có thể giải thích làm thế nào điều này sed lệnh hoạt động?

sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"

8
2017-10-04 08:13


gốc


Cách thông thường để làm điều này là sử dụng dấu gạch chéo, nhưng điều đó có thể trở nên rườm rà nếu bạn tìm kiếm và thay thế một cái gì đó bằng dấu gạch chéo. Đó không phải là trường hợp ở đây, do đó, mặc dù nó là hoàn toàn tốt, nó gây nhầm lẫn các nhà duy trì trong tương lai như bạn. - Thorbjørn Ravn Andersen
... và dẫn họ đến tìm hiểu điều gì đó mới mẻ về sed cách này! :) - dessert


Các câu trả lời:


Trong sed, các lệnh thay thế thường được viết là s/pattern/replacement/options. Tuy nhiên, không cần thiết phải sử dụng / - bạn có thể sử dụng các ký tự khác nếu nó thuận tiện, vì vậy nó có thể s@pattern@replacement@options hoặc là s:foo:bar:g. s@+@ @g giống như s/+/ /g - thay thế tất cả + với không gian. Tương tự s@%@\\x@g thay thế tất cả % với \x (một dấu gạch chéo ngược duy nhất là một ký tự thoát trong sed, vì vậy bạn cần hai để có được một dấu gạch chéo ngược thực tế).

Một chuỗi như foo+%2Fbar sau đó sẽ trở thành foo \x2Fbar. printf "%b" sẽ mở rộng trình tự thoát được dấu gạch chéo ngược như \x2F (ký tự ASCII có giá trị thập lục phân là 2F, là /) cuối cùng sẽ cung cấp cho bạn foo /bar.


15
2017-10-04 08:32



Tóm lại, một bộ giải mã URL-> tên tập tin. - Thorbjørn Ravn Andersen


Lệnh bạn đang yêu cầu để giải mã +es và % chuỗi từ URL không chỉ là một sed lệnh, đó là một đường ống xử lý đầu vào bằng sed, sau đó dẫn nó đến xargs để tiếp tục xử lý. Đầu tiên hãy nhìn vào sed chỉ huy:

sed 's@+@ @g;s@%@\\x@g'

Bạn có thể quen với việc thấy nó với / thay vì @ làm dấu phân tách, có thể dễ dàng thực hiện ở đây mà không có biến chứng kể từ / xuất hiện trong cả các mẫu tìm kiếm cũng như một trong các văn bản thay thế. Lệnh này tương đương:

sed 's/+/ /g;s/%/\\x/g'

Như /, @ là một ký tự dấu câu hoàn toàn tốt cho sed.

Trên mỗi dòng đầu vào:

  1. s@+@ @g (s/+/ /g) thay thế (s) sự xuất hiện của + với một không gian. Điều này ảnh hưởng đến tất cả +es trên một dòng (g), không chỉ là cái đầu tiên.

  2. ; kết thúc hành động ("lệnh") và cho phép bạn chỉ định một hành động khác trong cùng một "tập lệnh".

  3. s@%@\\x@g (s/%/\\x/g) thay thế (s) sự xuất hiện của % với \x. Như trước đây, nó hoạt động trên tất cả thay vì chỉ là đầu tiên của mỗi dòng (g).

    Trong \\x các \\ đại diện cho một \ bởi vì \ có ý nghĩa đặc biệt đối với sed. Ý nghĩa đặc biệt của nó thực sự là nhân vật bạn sử dụng để lấy đi ý nghĩa đặc biệt của một nhân vật khác xuất hiện sau khi nó có ý nghĩa đặc biệt. Vì vậy, nó phải được thoát như \\.


Bây giờ hãy nhìn một xargs lệnh, mục đích của nó là chạy printf.

xargs xây dựng các dòng lệnh. Nếu bạn chạy xargs chỉ huy..., Ở đâu command... là một hoặc nhiều từ, xargs chạy command... với bổ sung đối số dòng lệnh đọc từ đầu vào của nó. Trong trường hợp này, đầu vào xargs là đầu ra của sed, bởi vì đường ống (|). Thông thường xargs diễn giải bất kỳ khoảng trống nào trong đầu vào của nó để có nghĩa là văn bản trước và sau khi nó tạo thành các đối số riêng biệt, nhưng -0 tùy chọn làm cho nó tách đối số tại các lần xuất hiện của ký tự rỗng thay thế.

Trong mục đích sử dụng lệnh của bạn, một ký tự rỗng sẽ không xuất hiện và xargs sẽ chạy printf %b chỉ với một đối số dòng lệnh bổ sung, đầu ra của sed chỉ huy. Vì vậy, trong khi không tương đương nói chung, trong trường hợp này, toàn bộ đường ống có thể được viết như thế này bằng cách sử dụng thay thế lệnh thay vì xargs:

printf '%b\n' "$(sed 's/+/ /g;s/%/\\x/g')"

Về cái gì printf được dự định làm ở đây, như muru nói các %b định dạng specifier tiêu thụ và in một đối số (như %s) nhưng gây ra dấu gạch chéo ngược - trong số các loại sed lệnh ở phía bên trái của đường ống được viết để tạo ra - được được dịch sang các ký tự mà chúng đại diện.

Giả sử tôi chạy lệnh đó và vượt qua http://foldoc.org/debugging%20by%20printf làm đầu vào. tôi có http://foldoc.org/debugging by printf là đầu ra, bởi vì %20 trình tự được dịch sang không gian.


10
2017-10-04 09:31





Đó là vẻ đẹp của sed, nó áp dụng các mô hình của nó cho chính nó ... Sau lệnh (chẳng hạn như s hoặc là tr hoặc không có gì), ký tự tiếp theo được coi là dấu tách.

Bạn nên chọn một cách khôn ngoan để tránh sự can thiệp với vỏ và lệnh của chính nó, và giữ cho mọi thứ có thể đọc được, nhưng nó hoàn toàn hợp lệ để viết một cái gì đó thật kinh khủng như:

echo 'arrival' | sed srarbrg

...và lấy brrivbl do đó, đó là những gì bạn mong đợi. Bạn có thể vui vẻ làm cho nó thực sự khó hiểu, chẳng hạn như trong:

echo 'arrival' | sed s\fa\fb\fg   # \f is form feed, chr(12)

Việc sử dụng phổ biến là sử dụng dấu gạch chéo làm dấu phân cách, nhưng khi biểu thức của bạn chứa dấu phân cách, nó giúp dễ dàng nắm bắt ý định của nó. Dấu phân cách của bạn có thể là bất kỳ thứ gì trong phạm vi ASCII8 (các dấu phân cách nhiều byte chẳng hạn như £ kích hoạt một lỗi).

Chỉ cần nhớ mục tiêu là làm mọi thứ dễ dàng hơn, không khó hiểu hơn.


3
2017-10-04 14:12



Chạy với ý tưởng bí ẩn, đây là lệnh sed hợp lệ, mặc dù nó không làm bất cứ điều gì hữu ích: sed "snack is an apple or something" <<< "I sed your snack is an apple or something" - wjandrea
Tốt đẹp! Có, bạn có thể sử dụng sed các lệnh như trêu ghẹo não quá, geeky thế nào? - Marabiloso