
POSIX sh 또는 Bourne 쉘(Solaris 10의 경우와 같이)에서 /bin/sh
다음과 같은 것을 가질 수 있습니까?
a='some var with spaces and a special space'
printf "%s\n" $a
그리고 기본값을 사용하면 IFS
다음을 얻을 수 있습니다.
some
var
with
spaces
and
a
special space
즉, 인용 또는 이스케이프의 조합으로 special
사이 의 공간을 보호합니까?space
단어 수를 a
미리 알 수 없거나 다음과 같이 시도합니다.
a='some var with spaces and a special\ space'
printf "%s\n" "$a" | while read field1 field2 ...
맥락은이 버그OP가 JVM에 대한 옵션을 지정하는 환경 변수를 설정하려고 시도한 Cassandra에서 보고되었습니다.
export JVM_EXTRA_OPTS='-XX:OnOutOfMemoryError="echo oh_no"'
POSIX sh 및 Solaris sh를 지원해야 하는 Cassandra를 실행하는 스크립트에서:
JVM_OPTS="$JVM_OPTS $JVM_EXTRA_OPTS"
#...
exec $NUMACTL "$JAVA" $JVM_OPTS $cassandra_parms -cp "$CLASSPATH" $props "$class"
IMO에서 유일한 방법은 echo oh_no
명령을 래핑하는 스크립트를 사용하는 것입니다. 다른 방법이 있나요?
답변1
설마.
한 가지 해결 방법은 문자를 필드 구분 기호로 예약하는 것입니다. 당연히 해당 문자가 무엇이든 옵션에 포함시키는 것은 불가능합니다. 소스 언어에서 쉽게 삽입할 수 있다면 탭과 개행 문자는 확실한 후보입니다. 이식성을 원한다면 멀티바이트 문자를 사용하지 않는 것이 좋습니다(예: 대시 및 BusyBox는 멀티바이트 문자를 지원하지 않습니다).
IFS 분할에 의존하는 경우 set -f
.
tab=$(printf '\t')
IFS=$tab
set -f
exec java $JVM_EXTRA_OPTS …
또 다른 접근 방식은 인용 구문을 도입하는 것입니다. 매우 일반적인 인용 구문은 백슬래시가 다음 문자를 보호한다는 것입니다. 백슬래시 사용의 단점은 너무 많은 도구에서 백슬래시를 인용 문자로 사용하기 때문에 필요한 백슬래시 수를 파악하기 어려울 수 있다는 것입니다.
set java
eval 'set -- "$@"' $(printf '%s\n' "$JVM_EXTRA_OPTS" | sed -e 's/[^ ]/\\&/g' -e 's/\\\\/\\/g') …
exec "$@"
답변2
Bash나 이와 유사한 것을 사용하고 있다면 배열이 그 역할을 할 것입니다:
a=(some var with spaces and a 'special space')
그러나 POSIX 쉘에는 이러한 기능이 없기 때문에 제가 볼 수 있는 가장 좋은 내부 접근 방식은 실제로 특수 공간을 사용하는 것입니다. 줄바꿈하지 않는 공백(U+00A0)은 이 목적에 매우 적합하지만 ASCII 외부에는 스크립트의 문자 집합에 대한 동의가 필요합니다.
a="some var with spaces and a special space"
# this is a non-breaking space ------^
echo "$a" \
| while read word; do printf '%s\n' ${word} | sed 's@ @ @g'; done
# this is a non-breaking space ----------------------^
이는 다음을 출력합니다:
some
var
with
spaces
and
a
special space
현재로서는 이것을 변수 확장에 어떻게 포함할지 확신할 수 없지만(하위 쉘이 필요함) 이는 추가 조사를 위한 출발점이 될 것입니다.