Bash 변수의 특정 공간 확장을 피하는 방법은 무엇입니까?
나한테 이게 있다고 해보자.
JAVA_OPTS="-Xmx1g"
JAVA_OPTS="$JAVA_OPTS -XX:OnError='/path/to/a/script.sh %p'"
function args() {
printf "%d :" $#
printf " <%s> " $@
echo
}
args $JAVA_OPTS
당신은 이해했다
3 : <-Xmx1g> <-XX:OnError='/path/to/a/script.sh> <%p'>
나는 이것을 원한다
2 : <-Xmx1g> <-XX:OnError='/path/to/a/script.sh %p'>
답변1
먼저 args
하나의 인수만 제공하더라도 두 개의 인수가 표시됩니다.
$ args "abc def"
1 : <abc> <def>
올바르게 표시하려면 큰따옴표를 추가해야 합니다.
$ function args() { printf "%d :" $#; printf " <%s> " "$@"; echo; }
$ args "abc def"
1 : <abc def>
그러나 의 정의에는 여전히 문제가 있다 JAVA_OPTS
. 관찰하다:
$ args $JAVA_OPTS
3 : <-Xmx1g> <-XX:OnError='/path/to/a/script.sh> <%p'>
$JAVA_OPTS
이는 셸이 명령줄에 나타날 때 JAVA_OPTS의 내용을 토큰화하지만 그 안에 포함된 따옴표를 존중하거나 처리하지 않기 때문입니다 .
이러한 유형의 애플리케이션의 경우 JAVA_OPTS를 bash 배열로 정의하는 것이 더 좋습니다.
$ JAVA_OPTS="-Xmx1g"
$ JAVA_OPTS=("$JAVA_OPTS" "-XX:OnError=/path/to/a/script.sh %p")
$ args "${JAVA_OPTS[@]}"
2 : <-Xmx1g> <-XX:OnError=/path/to/a/script.sh %p>
그런데 배열로 작업할 때 배열의 내용을 확인하는 편리한 방법은 다음과 같습니다 declare -p
.
$ declare -p JAVA_OPTS
declare -a JAVA_OPTS='([0]="-Xmx1g" [1]="-XX:OnError=/path/to/a/script.sh %p")'
답변2
당신은대량으로대신에:
declare -a JAVA_OPTS
JAVA_OPTS+=("-Xmx1g")
JAVA_OPTS+=("-XX:OnError='/path/to/a/script.sh %p'")
args "${JAVA_OPTS[@]}"
문자열에 무언가가 있으면 단어 분리에 사용할 공백을 선택할 수 없지만 배열을 사용하면 해당 공백을 넣을 시기와 다시 꺼낼 시기를 결정할 수 있습니다. $@
내부적으로도 인용 해야 합니다 args
. 그렇지 않으면 손상될 것입니다.
실제로 단일 문자열로 정의해야 하는 경우 요소를 다른 문자로 분할하고 재설정할 수 있습니다.IFS
:
JAVA_OPTS="-Xmx1g"
JAVA_OPTS="$JAVA_OPTS|-XX:OnError='/path/to/a/script.sh %p'")
IFS="|"
args $JAVA_OPTS
비록 매우 연약하더라도 이 상황에서도 옳은 일을 합니다. 언제나 그렇듯이 를 저장하고 재설정 IFS
하거나 서브셸에서 변경을 수행하고 싶습니다.
답변3
다시 쉘의 파서를 전달할 수 있습니다:
var="'-Xmx1g' \"-XX:OnError='/path/to/a/script.sh %p'\""
eval "echo $var"
산출
-Xmx1g -XX:OnError='/path/to/a/script.sh %p'
하지만 아마도 배열이 가장 좋을 것입니다.
set -- '-Xmx1g "-XX:OnError='/path/to/a/script.sh %p'"
echo "item count $#"
for i do
echo "item#$((n=$n+1)): $i"
done
echo "$@"
산출
item count 2
item#1: -Xmx1g
item#2: -XX:OnError='/path/to/a/script.sh %p'
-Xmx1g -XX:OnError='/path/to/a/script.sh %p'
반드시 상호 배타적인 것은 아니지만:
eval "set $var"
item count 2
item#1: -Xmx1g
item#2: -XX:OnError='/path/to/a/script.sh %p'
-Xmx1g -XX:OnError='/path/to/a/script.sh %p'
예를 들어 함수 내에서 args()
두 개의 인수를 연결하려면 해당 인수 배열을 재설정하면 됩니다.
args() {
[ $# -gt 2 ] && {
a=$1; shift
set -- "$a" "$*"
} ; printf "%d :" $#
printf " <%s> " "$@"
echo
}
그러나 그것은 물류입니다. 이러한 변수를 배열에 포함하려면 다음을 수행하십시오.
args() {
printf "%d :" $#
printf " <%s> " "$@"
echo
}
args "$JAVA_OPTS" "-XX:OnError='/path/to/a/script.sh %p'"
또는 현재 쉘 배열의 경우 ..
set -- "$JAVA_OPTS" "-XX:OnError='/path/to/a/script.sh %p'"
모든 테이블 출력:
2 : <-Xmx1g> <-XX:OnError='/path/to/a/script.sh %p'>
어느 시점에 배열에 추가하고 싶다면:
set -- "$@" "some ne
w arg"
args "$@"
3 : <-Xmx1g> <-XX:OnError='/path/to/a/script.sh %p'> <some ne
w arg>
어레이는 엔클로저와 함께 제공됩니다. 당신은 그것을 사용해야합니다.