변수의 특정 공백이 확장되는 것을 방지

변수의 특정 공백이 확장되는 것을 방지

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> 

어레이는 엔클로저와 함께 제공됩니다. 당신은 그것을 사용해야합니다.

관련 정보