점(.)이 포함된 변수 내보내기

점(.)이 포함된 변수 내보내기

점이 있는 변수를 내보내는 방법 시도했을 때 '잘못된 변수 이름'이 표시됩니다.

 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

답변1

적어도 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가 식별자에 대해 매우 유사한 정의를 가지고 있으므로 이러한 종류의 변수도 허용하지 않는다고 확신합니다. (맨 페이지를 살펴보십시오.)

또한 식별자(따라서 변수 이름)로 허용되는 것이 무엇인지 지정하는 일종의 일반 표준(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"}'

경로를 인쇄해야합니다.

답변2

환경 변수는 등호 또는 널 바이트를 포함하지 않는 모든 이름(빈 문자열 포함)을 가질 수 있지만 쉘은 환경 변수를 쉘 변수에 매핑하며 대부분의 쉘에서 변수 이름은 ASCII 영숫자 문자로 제한되며 _첫 번째 문자는 숫자가 아니어야 합니다(위치 매개변수 및 $*, $-, $@, ...,(해당 환경 변수에 매핑되지 않음)과 같은 기타 특수 매개변수는 제외). 또한 일부 변수는 다음과 같습니다.예약/특별쉘에 의해/쉘에.

이에 대한 예외:

  • rc및 그 파생물은 빈 문자열을 제외한 모든 이름과 모두 숫자이거나 문자를 포함하는 이름을 지원합니다 es( 항상 모든 변수를 환경으로 내보내고 , , ... 와 같은 특수 변수에 주의하세요 ).akanga=*statuspid

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

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

    $ 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및 ( 단일 바이트 문자에만 해당)은 ASCII 뿐만 아니라 현재 로케일의 alnum도 지원합니다 yash.zshbash

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

    해당 쉘에서는 대부분의 문자를 알파로 간주하도록 로케일을 변경할 수 있지만 여전히 .. 문자라고 생각 zsh하거나 속일 수는 있지만 그 문자 나 다른 ASCII 문자는 그렇지 않습니다( 예를 들어 glob에 대한 것이 아니라 변수 이름에 문자를 허용하는 것이 관련됩니다).ksh£.[[:alpha:]]

  • ksh93와 같이 이름에 점이 포함된 특수 변수가 있지만 ${.sh.version}환경 변수에 매핑되지 않고 특별합니다. .다른 변수와 충돌하지 않는지 확인하는 것입니다 . 호출하기로 선택한 경우 $sh_version해당 변수를 이미 사용한 스크립트가 잠재적으로 손상되었을 수 있습니다(예를 들어 일부 스크립트를 손상시키는 해당 변수 또는 특수 배열/해시 변수(a la csh) zsh에 문제가 있는 방법을 참조하세요).$path$commands

해당 변수를 지원하지 않는 쉘 외에도 pdksh/mksh와 같은 일부 쉘은 이러한 변수를 지원합니다.제거하다수신하는 환경에서 해당 항목을 삭제합니다( 이름 bash이 비어 있는 항목을 제거 ash하고 문자가 포함되지 않은 환경 문자열을 제거함 ).kshbash=

$ 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="$$"

(이것은 Linux amd64에서 zsh, yash및 작동하는 것 같지만 내가 시도한 다른 쉘( , , , )에서는 csh작동 하지 않습니다 .)tcshmkshksh93bashdash

답변3

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

그러나 이러한 각 상황에서 해당 키-값 쌍은 환경 변수 이외의 다른 수단을 통해 프로그램에 전달될 수 있습니다. 예를 들어 Ant에서는 "-propertyfile(파일 이름)"을 사용하여 속성 파일 형식의 키-값 컬렉션을 전달할 수 있습니다. Confd는 "-백엔드 파일 -파일(yaml 파일)"을 허용합니다.

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

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

Borne Shell의 명령 set은 각 속성을 다음 형식의 별도 줄에 출력합니다.

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

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

답변4

export@michas의 답변은 매우 정확하지만 도트 환경 이름을 사용하여 기능을 시뮬레이션하도록 확장할 수 있습니다 .

exec이러한 변수를 "내보내기"하려면 명령을 사용하여 현재 쉘을 사용할 수 있습니다 env. 예를 들어 변수를 내보내려면 다음을 test.env=foo사용합니다.

exec env "test.env=foo" $SHELL

Exec은 현재 셸을 새 프로세스로 대체합니다. 여기서 새 프로세스는 $SHELL추가 환경 변수 test.env(에 의해 추가됨 env "test.env=foo")가 있는 현재 셸( )의 새 인스턴스가 됩니다. 따라서 이 명령 후에 프로세스에서 액세스할 수 있습니다. 예:

perl -e 'print $ENV{"test.env"}'

관련 정보