Bạn không thể, có thể, đặt nhiều hơn một đối số trên một #!
dòng . Điều đó có nghĩa là chỉ một đường dẫn đầy đủ và một đối số (ví dụ:#!/bin/sed -f
hoặc #!/usr/bin/sed -f
) hoặc #!/usr/bin/env
không có đối số cho trình thông dịch.
Một cách giải quyết để có được một tập lệnh di động là sử dụng #!/bin/sh
và trình bao bọc shell, chuyển tập lệnh sed làm đối số dòng lệnh. Lưu ý rằng điều này không bị POSIX xử phạt (tập lệnh đa hướng dẫn phải được viết bằng một -e
đối số riêng cho mỗi hướng dẫn về tính di động), nhưng nó hoạt động với nhiều triển khai.
#!/bin/sh
exec sed '
s/a/b/
' "$@"
Đối với một kịch bản dài, có thể thuận tiện hơn khi sử dụng một di sản. Một lợi thế của một di sản là bạn không cần trích dẫn các trích dẫn duy nhất bên trong, nếu có. Một nhược điểm lớn là tập lệnh được đưa vào sed trên đầu vào tiêu chuẩn của nó, với hai hậu quả khó chịu. Một số phiên bản của sed yêu cầu -f /dev/stdin
thay vì -f -
, đó là một vấn đề cho tính di động. Tệ hơn, tập lệnh không thể hoạt động như một bộ lọc, vì đầu vào tiêu chuẩn là tập lệnh và không thể là dữ liệu.
#!/bin/sh
exec sed -f - -- "$@" <<'EOF'
s/a/b/
EOF
Nhược điểm của di truyền có thể được khắc phục bằng cách sử dụng hữu ích cat
. Vì điều này đặt lại toàn bộ tập lệnh trên dòng lệnh, nó không tuân thủ POSIX, nhưng phần lớn có thể di động trong thực tế.
#!/bin/sh
exec sed "$(cat <<'EOF')" -- "$@"
s/a/b/
EOF
Một cách giải quyết khác là viết một tập lệnh có thể được phân tích cú pháp bằng cả sh và bởi sed. Đây là di động, hợp lý hiệu quả, chỉ là một chút xấu xí.
#! /bin/sh
b ()
{
x
}
i\
f true; then exec sed -f "$0" "$@"; fi
: ()
# sed script starts here
s/a/b/
Giải thích:
- Theo sh: định nghĩa một hàm được gọi
b
; nội dung không quan trọng miễn là chức năng được hình thành tốt về mặt cú pháp (đặc biệt, bạn không thể có chức năng trống). Sau đó, nếu đúng (tức là luôn luôn), thực hiện sed
trên kịch bản.
- Dưới sed: nhánh đến
()
nhãn, sau đó một số đầu vào được hình thành tốt. Sau đó, một i
lệnh, không có hiệu lực vì nó luôn bị bỏ qua. Cuối cùng, ()
nhãn tiếp theo là phần hữu ích của tập lệnh.
- Đã thử nghiệm dưới GNU sed, BusyBox và OpenBSD. (Bạn có thể thoát khỏi một cái gì đó đơn giản hơn trên GNU sed, nhưng OpenBSD sed rất kén chọn các phần mà nó bỏ qua.)