Là mở rộng tham số trên $ @ không được hỗ trợ bởi sh shell?


8

Tôi đã đăng câu trả lời cho một câu hỏi trên AU và tôi thấy rằng việc mở rộng tham số trên $@không hoạt động với trình shbao:

<infile xargs -d'\n' sh -c 'echo "${@%%/*}"' _

nhưng nó hoạt động tốt trong bash. Đây có phải là hành vi dự kiến ​​của shshell và làm thế nào tôi có thể thực hiện mở rộng ở đó?

Ngoài ra, tôi biết rằng với -n1tùy chọn xargstôi chỉ có thể truyền một dòng cho lệnh tại một thời điểm, nhưng tôi quan tâm đến việc shcó thể mở rộng $@:

<infile xargs -d'\n' -n1 sh -c 'echo "${0%%/*}"'

infile chứa đựng:

A1 /B1/C1
A 2/B2/C2
A3/B3/C3

Câu trả lời:


12

Đúng, dấu gạch ngang dường như ít hữu ích hơn ở đây. Mặc dù nó không có lỗi, nói đúng, như ${@%...}không xác định bởi POSIX :

Bốn giống mở rộng tham số sau đây cung cấp cho xử lý chuỗi con. [...] Nếu tham số là ' #', ' *' hoặc ' @', kết quả của việc mở rộng là không xác định.

Mặc dù điều này thật kỳ lạ, có vẻ như nếu một bản mở rộng như thế sửa đổi phần cuối của một tham số vị trí, thì nó sẽ loại bỏ các tham số sau. Nhưng không, nếu nó không thực sự sửa đổi kết thúc:

$ dash -c 'set -- foo bar; printf "<%s>\n" "${@%o}";'
<fo>
$ dash -c 'set -- foo bar; printf "<%s>\n" "${@%x}";'
<foo>
<bar>
$ dash -c 'set -- foo bar doo; printf "<%s>\n" "${@%r}";'
<foo>
<ba>

Bash, ksh và Zsh dường như đều xử lý "${@#...}""${@%...}"bằng cách xử lý từng tham số vị trí một cách độc lập, điều này dường như là điều hữu ích để làm.

Tôi cho rằng cách giải quyết rõ ràng dashlà thực hiện sửa đổi một đối số tại một thời điểm:

for x in "$@"; do echo "${x%%/*}"; done

Đối với giá trị của nó, hành vi của các mở rộng loại bỏ tiền tố / hậu tố được sử dụng $*cũng khác nhau giữa các shell. Bash và ksh dường như sửa đổi các tham số trước và tham gia chúng sau đó, trong khi Zsh và dash tham gia các tham số trước và sửa đổi chuỗi nối:

$ zsh -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a>
$ bash -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a b>

âm thanh shnghĩ $@là một tham số duy nhất cho toàn bộ tệp (hoặc sẽ phá vỡ thành nhiều nếu vượt quá ARG_MAX) và thực hiện mở rộng trên đối số duy nhất.
αғsнιη

1
Cũng lưu ý rằng pdksh và các dẫn xuất cung cấp cho bạn một Bad substitutionlỗi trên mã đó. Đối với ${*%pattern}, bạn thấy một số biến thể trong hành vi trong những thứ như"$shell" -c 'printf "<%s>\n" "${*%x*}"' sh ax by
Stéphane Chazelas

1
@ αғsнιη, nó không đơn giản. lưu ý ví dụ thứ hai trong đó việc mở rộng để lại các tham số vị trí dưới dạng các từ riêng biệt. Và tôi không nghĩ ARG_MAXđến nó, việc xử lý là nội bộ.
ilkkachu
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.