명시적인 빈 문자열로 확장되도록 변수를 설정하시겠습니까?

명시적인 빈 문자열로 확장되도록 변수를 설정하시겠습니까?

다음과 같은 쉘 스크립트( example)가 있습니다(단순화).

#!/bin/sh
./somecommand -s ${DOMAIN_SUFFIX:=.example.com}

실행하면 ./example올바르게 실행됩니다 ./somecommand -s .example.com.

실행하면 DOMAIN_SUFFIX=.stackexchange.com ./example올바르게 실행됩니다 ./somecommand -s .stackexchange.com.

DOMAIN_SUFFIX질문: (스크립트 내에서) 명시적인 빈 문자열로 전달되도록 어떻게 설정합니까 ?

즉, 실행하려면 필요합니다 ./somecommand -s ''.

이것을 시도했지만 실행 DOMAIN_SUFFIX='' ./example./somecommand -s실패했습니다.

답변1

쉘이 모든 확장을 수행하고 빈 필드로 끝난 후에는 인용되지 않는 한 삭제됩니다. 변수를 참조하고 있지 않으므로 빈 ""으로 확인되면 "somecommands" 매개변수 목록에서 해당 변수를 제거해야 합니다. 그뿐만 아니라 DOMAIN_SUFFIX에 공백이나 와일드카드가 있는 경우 "somecommand"에 놀랄 수도 있습니다.

또한 ${DOMAIN_SUFFIX:=.example.com}은 표시된 결과에 따른 오타입니다. DOMAIN_SUFFIX='' ./example왜냐하면 빈 DOMAIN_SUFFIX가 이를 기본값으로 대체한 다음 일부 명령의 인수 목록에 배치하기 때문입니다. 따라서 "null"이 표시되지 않습니다. ${DOMAIN=.example.com}당신이 얻는 결과를 설명 할 것입니다.

답변2

사용:

"${DOMAIN_SUFFIX=.example.com}"

${매개변수=기본값}, ${매개변수:=기본값}

매개변수가 설정되지 않은 경우 기본값으로 설정됩니다.

두 형태 모두 거의 동일합니다. : $parameter가 선언되고 null인 경우에만 효과가 있습니다.

http://www.tldp.org/LDP/abs/html/parameter-substitution.html

보간 후 null 값이 삭제되는 것을 방지하려면 따옴표가 필요합니다 ""(코드에 null 값이 누락된 것을 확인했습니다. @Gilles에게 감사드립니다!).

또한 =(또는 )은 설정되지 않은 경우 DOMAIN_SUFFIX에 기본값을 할당하므로 해당 값만 가져와야 하는 경우 이를 :=사용할 수 있습니다 .-

답변3

TL, 박사:공백이나 기타 특수 문자 때문에 쉘 스크립트가 멈추는 이유는 무엇입니까?. 이런, 이건 더 길었습니다... 좋아요, 진짜 TL, DR: 변수와 ​​명령 대체에는 항상 큰따옴표를 넣으세요. 또한 스크립트의 두 번째 문제에 대해서는 이 답변의 끝을 참조하세요.

스크립트에서 변수를 빈 문자열로 확장하는 것은 불가능합니다. 따옴표 없는 변수 확장은 "expand+split+glob" 프로세스를 거칩니다.

  1. 문자열인 변수의 값을 가져옵니다.
  2. 공백에서 문자열을 분할합니다(더 일반적으로는 변수 값에 있는 문자에서 IFS). 그러면 문자열 목록이 생성됩니다(원래 문자열에 공백만 포함된 경우 비어 있을 수 있음).
  3. 목록의 각 요소에 대해 하나 이상의 와일드카드 문자가 포함되어 있고 *?\[요소가 하나 이상의 파일과 일치하는 패턴인 경우 해당 요소는 일치하는 목록으로 대체됩니다.

$DOMAIN_SUFFIX빈 문자열 목록으로 확장 할 수 있지만 빈 문자열이 포함된 목록으로는 확장할 수 없습니다. 파일 이름은 결코 빈 문자열이 아니기 때문에 와일드카드 일치 단계에서는 빈 요소를 생성할 수 없습니다. 분할 단계에서는 IFS구분 기호가 일련의 공백이고 일련의 공백을 끊으려면 공백이 아닌 문자가 하나 이상 필요하기 때문에 기본값이 로 설정되는 빈 요소를 생성할 수 없습니다. 공백이 아닌 문자를 포함하도록 변경하면 분할 단계에서 빈 요소가 생성될 수 있지만 IFS이를 수정하려면 스크립트 변경이 필요하며 IFS그렇게 할 이유가 없습니다.

Expand+split+glob 연산자를 사용하는 대신 스크립트를 변경하고 간단한 변수 확장을 사용하도록 해야 합니다. 즉, 변수 확장 주위에 큰따옴표를 넣으십시오.

또한 의 값이 비어 있으면 ${DOMAIN_SUFFIX:=.example.com}로 확장됩니다. 따라서 빈 문자열을 얻지 못합니다. null 값을 유지하고 설정되지 않은 경우에만 사용하려면 로 변경합니다..example.comDOMAIN_SUFFIX.example.comDOMAIN_SUFFIX:==

#!/bin/sh
./somecommand -s "${DOMAIN_SUFFIX=.example.com}"

답변4

bash나는 이것이 당신이 찾고 있는 매뉴얼의 일부라고 생각합니다(POSIX는비슷한 표현은 같은 효과를 가집니다):

부분 문자열 확장이 수행되지 않으면 아래에 설명된 양식(예: :-) 을 사용하여 bash설정되지 않았거나 빈 인수를 테스트합니다. 콜론을 생략하면 설정되지 않은 매개변수만 테스트됩니다.

설정되지 않은 변수와 null 값이 있는 변수의 차이점은 설정되지 않은 변수가 존재하지 않는다는 것입니다.

그래서,

#!/bin/bash

bash -c 'echo "$#"; printf "%s\n" "$@"' -- "${DOMAIN_SUFFIX=.example.com}"

설정하지 않으면 해당 값으로 설정되고, null(빈 문자열)이면 설정되지 않습니다 DOMAIN_SUFFIX..example.comDOMAIN_SUFFIX

여기에 사용된 명령은 bash전달된 명령줄 인수 수와 그 뒤에 모든 위치 인수를 한 줄에 하나씩 인쇄하는 새 프로세스를 생성합니다.

bash-4.4$ bash script
1
.example.com
bash-4.4$ DOMAIN_SUFFIX=.hello.world bash script
1
.hello.world
bash-4.4$ DOMAIN_SUFFIX= bash script
1

bash-4.4$

마지막 예에서는 DOMAIN_SUFFIX=와 동일합니다 DOMAIN_SUFFIX=''.

관련 정보