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 ...
맥락은이 오류Cassandra에서 보고된 대로 OP는 JVM 옵션을 지정하는 환경 변수 설정을 시도했습니다.
export JVM_EXTRA_OPTS='-XX:OnOutOfMemoryError="echo oh_no"'
Cassandra를 실행하는 스크립트에서는 POSIX sh 및 Solaris sh를 지원해야 합니다.
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
현재로서는 이것을 변수 확장에 어떻게 포함해야 할지 잘 모르겠습니다(하위 쉘이 필요함). 그러나 이는 추가 조사를 위한 출발점이 될 것입니다.