Bất cứ ai có thể giải thích làm thế nào sed
lệnh này hoạt động?
sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
sed
cách này! :)
Bất cứ ai có thể giải thích làm thế nào sed
lệnh này hoạt động?
sed 's@+@ @g;s@%@\\x@g' | xargs -0 printf "%b"
sed
cách này! :)
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 thuận tiện, vì vậy nó có thể s@pattern@replacement@options
hoặc s:foo:bar:g
. s@+@ @g
giống như s/+/ /g
- thay thế tất cả +
bằng không gian. Tương tự s@%@\\x@g
thay thế tất cả %
bằng \x
(một dấu gạch chéo ngược là một ký tự thoát trong sed, vì vậy bạn cần hai 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 các chuỗi thoát dấu gạch chéo ngược như \x2F
(ký tự ASCII có giá trị thập lục phân là 2F, /
cuối cùng) để cung cấp cho bạn foo /bar
.
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 sed
, sau đó chuyển nó sang xargs
xử lý tiếp. Đầu tiên chúng ta hãy nhìn vào sed
lệnh:
sed 's@+@ @g;s@%@\\x@g'
Bạn có thể quen với việc nhìn thấy nó /
hơn @
là với dấu phân cách, điều có thể dễ dàng được thực hiện ở đây mà không có sự phức tạp vì /
xuất hiện trong cả các mẫu tìm kiếm cũng như các văn bản thay thế. Lệnh này tương đương:
sed 's/+/ /g;s/%/\\x/g'
Giống như /
, @
là một nhân vật chấm câu hoàn toàn tốt cho sed
.
Trên mỗi dòng đầu vào:
s@+@ @g
( s/+/ /g
) thay thế ( s
) lần xuất hiện của +
với một khoảng trắng. Điều này ảnh hưởng đến tất cả +
es trên một dòng ( g
), không chỉ cái đầu tiên.
;
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".
s@%@\\x@g
( s/%/\\x/g
) thay thế ( s
) lần 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ỉ đầu tiên của mỗi dòng ( g
).
Trong \\x
những \\
chỉ là một đại diện \
vì \
có một ý nghĩa đặc biệt để 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 nó sẽ có ý nghĩa đặc biệt. Vì vậy, nó phải được thoát như \\
.
Bây giờ hãy xem 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 , nơi có một hoặc nhiều từ, sẽ chạy với các đối số dòng lệnh bổ sung được đọc từ đầu vào của nó. Trong trường hợp này, đầu vào là đầu ra của , vì đường ống ( ). Thông thường 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 nó tạo thành các đối số riêng biệt, nhưng tùy chọn làm cho nó phân tách các đối số tại các lần xuất hiện của ký tự null .xargs command...
command...
xargs
command...
xargs
sed
|
xargs
-0
Trong mục đích sử dụng lệnh của bạn, một ký tự null 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
lệnh. Do đó, mặc dù 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')"
Đối với những gì printf
được dự định làm ở đây, như muru nói rằng trình %b
xác định định dạng tiêu thụ và in một đối số (như %s
) nhưng gây ra dấu gạch chéo ngược - của lệnh sắp xếp sed
bên trái của đường ống được viết để tạo - được dịch vào các nhân vật mà họ đại diện .
Giả sử tôi chạy lệnh đó và chuyển http://foldoc.org/debugging%20by%20printf
làm đầu vào. Tôi nhận được http://foldoc.org/debugging by printf
như là đầu ra, bởi vì các %20
chuỗi được dịch vào không gian.
Đó là vẻ đẹp của sed
, nó áp dụng mô hình của mình cho bản thân ... Sau khi lệnh (chẳng hạn như s
hay tr
hoặc không có gì), nhân vật tiếp theo được coi là tách.
Bạn nên chọn một cách khôn ngoan để tránh sự can thiệp vào trình bao và chính lệnh đó, 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ì đó kinh khủng như:
echo 'arrival' | sed srarbrg
... Và nhận được brrivbl
kết quả, đó 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ó sẽ giúp bạn dễ dàng nắm bắt ý định đó là gì. Dấu phân cách của bạn có thể là bất cứ thứ gì trong phạm vi ASCII8 (các dấu phân cách đa dòng như £
gây ra lỗi).
Chỉ cần nhớ mục tiêu là làm cho mọi thứ dễ dàng hơn, không khó hiểu hơn.
sed "snack is an apple or something" <<< "I sed your snack is an apple or something"
sed
các lệnh như trêu ghẹo não quá, làm thế nào là geeky?