점 (.)이 포함 된 변수 내보내기 variable name 메타 문자 점

점이있는 변수를 내보내는 방법 시도 할 때 ‘잘못된 변수 이름’이 나타납니다.

 export my.home=/tmp/someDir
-ksh: my.home=/tmp/someDir: invalid variable name

메타 문자 점 (.)을 이스케이프 처리해도 도움이되지 않습니다.

$ export my\.home=/tmp/someDir
export: my.home=/tmp/someDir: is not an identifier


답변

최소한 bash매뉴얼 페이지에서 내보내기 구문을 다음과 같이 정의하십시오.

export [-fn] [name[=word]] ...

또한 “이름”을 다음과 같이 정의합니다.

   name   A  word  consisting  only  of alphanumeric characters and under
          scores, and beginning with an alphabetic character or an  under
          score.  Also referred to as an identifier.

따라서 my.home유효한 식별자가 아니므로 변수를 실제로 정의 할 수 없습니다 .

나는 당신의 ksh가 매우 유사한 식별자 정의를 가지고 있다고 확신하므로 이런 종류의 변수도 허용하지 않습니다. (Man 페이지를 살펴보십시오.)

또한 식별자 (및 변수 이름)로 허용되는 것을 지정하는 일종의 일반 표준 (POSIX?)이 있음을 확신합니다.


어떤 이유로 이런 종류의 변수가 정말로 필요한 경우 다음과 같은 것을 사용할 수 있습니다

env "my.home=/tmp/someDir" bash

어쨌든 그것을 정의합니다. 그러나 다시 일반 쉘 구문을 사용하여 액세스 할 수 없습니다. 이 경우 아마도 perl과 같은 다른 언어가 필요할 것입니다.

perl -e 'print $ENV{"my.home"}'

예를 들어

env "my.home=/tmp/someDir" perl -le 'print $ENV{"my.home"}'

경로를 인쇄해야합니다.


답변

환경 변수는 등호 또는 널 바이트를 포함하지 않는 모든 이름 (빈 문자열 포함)을 가질 수 있지만 쉘은 환경 변수를 쉘 변수와 대부분의 쉘에 맵핑하지만 변수 이름은 ASCII 영숫자로 제한되며 _첫 문자는 ‘ t는 자리 수 (위치 매개 변수와 같은 다른 특별한 사람을 제외한 $*, $-, $@, …, (해당 환경 변수에 매핑되지 않은)). 또한 일부 변수는 쉘에 의해 / 특별하게 예약되어 있습니다.

예외 :

  • rc쉘과 같은 그 유도체 esakanga빈 문자열을 제외한 모든 이름을 지원하고, 모든 숫자 또는 포함 된 것과 =문자 (항상하고 환경에 모든 변수를 내 보낸 특수 변수의 조심 좋아 *, status, pid…)

    ; '%$£"' = test
    ; echo $'%$£"'
    test
    ; '' = x
    zero-length variable name
    ;
    

    그러나 실행중인 명령 환경에 전달 될 때 이름에 숫자가 포함되지 않은 변수 나 배열에 대해 자체 인코딩을 사용합니다.

    $ rc -c '+ = zzz; __ = zzz; a = (zzz xxx); env' | sed -n /zzz/l
    __2b=zzz$
    __5f_=zzz$
    a=zzz\001xxx$
    $ env +=x rc -c "echo $'+'"
    x
    $ env __2b=x rc -c "echo $'+'"
    x
    
  • AT & T ksh, yashzsh(도 bash하지만, 1 바이트 문자) 현재의 지역뿐만 아니라 ASCII 것들에 지원 alnums.

    $ Stéphane=1
    $ echo "$Stéphane"
    1
    

    이러한 쉘에서는 대부분의 문자를 알파로 간주하도록 로케일을 변경할 수 있지만 여전히 ASCII 문자에는 작동하지 않습니다 .. 어리 석 zsh거나 ksh생각하는 £것은 문자이지만 .다른 ASCII 문자는 아닙니다 ( [[:alpha:]]예를 들어 , 변수 이름의 문자를 허용하는 것이 중요 합니다).

  • ksh93이름에 점과 같은 점이 포함 된 특수 변수가 ${.sh.version}있지만 환경 변수에 매핑되지 않고 특수합니다. 는 .확실이 다른 변수와 충돌하지 않는 확인하는 것입니다. 이 호출을 선택했다면 $sh_version, 그것은 잠재적 변수 이미 (방법, 예를 들어 볼 것을 사용하는 것이 스크립트를 부러 졌을 수 zsh의 문제를 가지고 $path또는 $commands일부 스크립트를 중단하는) 특별한 배열 / 해쉬 변수 (라 CSH).

이 변수를 지원하지 않는 쉘뿐만 아니라, 할 mksh pdksh 같은 같은 일부 포탄 / 참고 제거 그들이받는 환경에서 그들 ( bash빈 이름을 가진 하나를 제거 ash, ksh그리고 bash포함하지 않는 환경 문자열 분리 =문자) :

$ env %%%=test 1=%%% a.b=%%% mksh -c env | grep %%%
$ env %%%=test 1=%%% a.b=%%% bash -c env | grep %%%
%%%=test
a.b=%%%
1=%%%

$ perl -le '$ENV{""}="%%%"; exec "bash", "-c", "env"' | grep %%%
$ perl -le '$ENV{""}="%%%"; exec "zsh", "-c", "env"' | grep %%%
=%%%

$ echo 'main(){char*a[]={"sh","-c","env",0};char*e[]={"%%%",0};
    execve("/bin/ash",a,e);}'|tcc -run - | grep %%%
$ echo 'main(){char*a[]={"sh","-c","env",0};char*e[]={"%%%",0};
    execve("/bin/zsh",a,e);}'|tcc -run - | grep %%%
%%%

요약하면, 가장 (대부분의 쉘에서 지원하는 변수 이름을 고수하고 심지어 껍질에 특별한 그들을 피하는 환경 변수에 대한 대문자를 사용하려고 (그리고-수출 쉘 변수 경우 또는 혼합 소문자)하는 것 같은 IFS, PS1, BASH_VERSION…).

그러한 변수를 지원하지는 않지만 버리지 않는 쉘에 그러한 변수를 설정해야하는 경우, 다음과 같이 자신을 다시 실행할 수 있습니다.

#! /bin/ksh -
perl -e 'exit 1 unless defined($ENV{"a.b"})' || exec env a.b=%%% "$0" "$@"

(물론 스크립트 중간에 수행 해야하는 경우 도움이되지 않지만 다시 실행을 통해 쉘 실행 환경을 저장하고 복원 하는 방법 을 살펴볼 수 있습니다 ). 또는 디버거 접근 방식을 시도하십시오.

gdb --batch-silent -ex 'call putenv("a.b=%%%")' --pid="$$"

(하나와 함께 작동하도록 보인다 zsh, yash, cshtcsh리눅스 AMD64에서,하지만 내가 노력 다른 쉘 (의와 mksh, ksh93, bash, dash)).


답변

다른 게시물에서 지적했듯이 가장 일반적인 쉘은 이름에 마침표가있는 환경 변수를 설정할 수 없습니다. 그러나 특히 Docker 및 호출 된 프로그램과 관련된 상황을 발견했으며 소프트웨어에서 기간이있는 키 값이 필요했습니다.

그러나 이러한 각 상황에서 이러한 키-값 쌍은 환경 변수 이외의 다른 수단을 통해 프로그램에 전달 될 수 있습니다. 예를 들어 Ant에서 “-propertyfile (파일 이름)”을 사용하여 속성 파일 형식의 키-값 모음을 전달할 수 있습니다. confd는 “-backend file -file (yaml file)”을 허용합니다.

“C__any_value = ‘my.property.key = the value'”형식으로 환경 변수를 전달했습니다. 그런 다음 파일을 먼저 생성하도록 프로그램 호출을 전환했습니다.

set | awk -- 'BEGIN { FS="'\''" } /^C__/ {print $2}' > my-key-values.txt

setBorne Shell 의 명령은 각 속성을 양식의 별도 줄에 출력합니다.

C__any_value='my.property.key=the value'

awk명령은로 시작하는 환경 변수 만 처리 C__한 다음 작은 따옴표에 포함 된 값을 추출합니다.

이 방법을 사용하려면 환경 변수 값을 처리 프로그램에 필요한 정확한 형식으로 설정해야합니다. 또한 속성 값이나 키에 작은 따옴표가 포함되어 있으면 awk 필드 구분 문자를 표시되지 않는 것으로 변경하고 해당 문자로 값을 둘러싸 야합니다. 예를 들어 %구분 기호 로 사용하려면

$ C__1="%my.key=the'value%"
$ set | awk -- 'BEGIN { FS="%" } /^C__/ {print $2}'
my.key=the'"'"'value

(정확한 출력은 쉘에 따라 다릅니다.) 따옴표 이스케이프를 해독하려면 추가 단계를 수행해야합니다.