sh 쉘은 $@에서 매개변수 확장을 지원하지 않습니까?

sh 쉘은 $@에서 매개변수 확장을 지원하지 않습니까?

나는 출판했다답변AU에 대한 질문과 관련하여 매개변수 확장이 셸 $@에서 작동하지 않는다는 것을 발견했습니다.sh

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

하지만 작동합니다 bash. 이것이 쉘의 예상된 동작입니까 sh? 거기서 확장을 어떻게 수행합니까?

-n1또한 옵션을 통해 xargs한 번에 한 줄만 명령에 전달할 수 있다는 것을 알고 있지만 sh이것이 확장될 수 있는지에 관심이 있습니다 $@.

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

infile포함하다:

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

답변1

네, 여기서는 대시가 그다지 유용하지 않은 것 같습니다. 틀린말은 ${@%...}아니지만 엄밀히 말하면POSIX가 지정되지 않았습니다.:

다음 네 가지 매개변수 확장은 하위 문자열 처리를 제공합니다. [...] 인수가 " #", " *" 또는 " @"인 경우 확장 결과는 지정되지 않습니다.

그러나 이것은 이상합니다. 그러한 확장이 하나의 위치 매개변수의 끝을 수정하면 다음 위치 매개변수를 제거하는 것 같습니다. 그러나 실제로 결말을 수정하지 않는 경우에는 그렇지 않습니다.

$ 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 및 Zsh는 모두 각 위치 인수를 독립적으로 "${@#...}"처리하는 것으로 보이며 "${@%...}"이는 유용한 것 같습니다.

내 생각에 확실한 해결책은 dash한 번에 하나의 매개변수를 수정하는 것입니다.

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

그만한 가치가 있기 때문에 다른 쉘에서 사용되는 접두사/접미사 제거 확장의 동작은 $*다양합니다. Bash와 ksh는 매개변수를 먼저 수정한 다음 연결하는 것처럼 보이지만 Zsh와 대시는 매개변수를 먼저 연결한 다음 연결된 문자열을 수정합니다.

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

관련 정보