posix 쉘 : 환경 변수 이름의 인쇄 목록 (값 없음)


11

여러 구현에서 작동하는 posix 호환 방식으로 현재 정의 된 환경 변수 목록을 값 없이 인쇄하려면 어떻게 해야합니까?

일부 구현 (mksh, freebsd / bin / sh)에서는 단독으로 사용 export하는 것이 비용에 맞습니다.

$ export
FOO2
FOO

그러나 다른 구현 (bash, zsh, dash)의 export경우 값도 보여줍니다. bash를 사용하면 다음과 같습니다.

$ export
export FOO2='as  df\
  asdk=fja:\
asd=fa\
asdf'
export FOO='sjfkasjfd  kjasdf:\
   asdkj=fkajdsf:\
       :askjfkajsf=asdfkj:\
   safdkj'
$ printenv | sed -n l
FOO2=as\tdf\$
  asdk=fja:\$
asd=fa\$
asdf$
FOO=sjfkasjfd  kjasdf:\$
   asdkj=fkajdsf:\$
\t:askjfkajsf=asdfkj:\$
   safdkj$

같은 다른 옵션 env이나 printenv옵션이없는 적어도 아니라 리눅스와 내가 시도 FreeBSD의 플랫폼에서, 값없이 그냥 변수 이름을 인쇄합니다.

awk / sed / etc로 파이핑 또는 매개 변수 확장 기술 (예 :)을 사용하여 목록을 트리밍하는 ${foo%%=*}것은 허용되지만 값이 =공백이고 값에 공백이있을 수있는 값 (위의 예 참조)으로 작업해야합니다.

특정 쉘 구현에 대한 답변은 흥미 롭지 만 주로 구현 전반에서 호환되는 것을 찾고 있습니다.


2
무언가를 구문 분석하려는 경우 export -pPOSIX에서 지정한 출력을 사용하여 셸의 입력에도 적합한 출력을 생성하십시오.
Kusalananda

쉘에 입력 할 것이 필요하지 않습니다. 환경 변수의 이름 만 원합니다. 따라서 추가 크래프트 (예 : 각 줄의 앞쪽에있는 '내보내기'단어)를 제거해야합니다. 왜 export -p이것을 사용하고 싶 습니까?
Juan

1
원하는 export -p모든 POSIX 셸에서 일관된 출력을 제공 하기 때문에 사용하고 싶습니다 .
Kusalananda

쉘에서 일관된 솔루션 인 변수 이름 만 인쇄하는 솔루션을 원합니다. export -p값이없는 변수 이름 만 인쇄하는 첫 번째 요구 사항에 맞지 않습니다.
Juan

경우 당신이 구문 분석 뭔가거야,의 출력과 함께 할 것입니다 export -p. 일반적인 경우에는 값이 다음과 같은 변수가있는 경우 적절한 따옴표 구문 분석을 수행해야하기 때문에 해당 구문 분석을 작성하지 않겠습니다 hello\nexport var=value. 모든 POSIX 셸에서 일관된 출력을 제공 하는 몇 가지 다른 명령 중 하나는 입니다 env. 그러나 비트 가 없기 때문에 출력 을 구문 분석 하기더 어렵 습니다 export =.
Kusalananda

답변:


9

awk에서 꽤 쉽습니다.

awk 'BEGIN{for(v in ENVIRON) print v}'

그러나 일부 awk 구현은 자체 환경 변수를 추가합니다 (예 : GNU awk add AWKPATHAWKLIBPATHto ENVIRON).

환경 변수 이름에 줄 바꿈이 포함되어 있으면 출력이 모호합니다. 이는 매우 드문 일이지만 기술적으로 가능합니다. 순수한 쉬 솔루션은 어려울 것입니다. 가장 좋은 방법은 시작하는 export -p것이지만 순수한 sh로 마사지하는 것은 어렵습니다. sed를 사용하여의 출력을 마사지 export -p한 다음 eval셸을 사용 하여 인용 된 내용을 제거 할 수 있습니다. Bash 및 zsh는 비표준 접두사를 인쇄합니다.

report () { echo "${1%%=*}"; };
eval "$(export -p | sed "s/^export /report /;
                         s/^declare -x /report /;
                         s/typeset -x /report /")"

쉘에 따라 쉘에서 export -p이름이 유효하지 않은 변수를 표시하거나 표시하지 않을 수 있으며, 그렇지 않은 경우 이름을 올바르게 인용하거나 인용하지 않을 수 있습니다. 예를 들어, 대시, mksh 및 zsh는 이름에 개행 문자가 포함 된 변수를 생략하고 BusyBox dash 및 ksh93은 변수를 원시로 인쇄하고 bash는 값없이 원시를 인쇄합니다. 신뢰할 수없는 입력에 대해 방어해야하는 경우 순수한 POSIX 솔루션을 사용하지 말고 eval의 출력에서 ​​파생 된 항목을 호출하지 마십시오 export -p.


여러 줄 값을 가진 sed (1)를 사용하여 실제로 얼마나 "쉬운"지 잘 모르겠습니다. 그러나 awk (1) 방법에 감사드립니다. 나는 이것이 지금까지 가장 휴대용 방법이라고 생각합니다 exit(필요 하다고 생각하지는 않지만 ).
Juan

당신이 얻을 경우주의 FOO<newline>BAR, 당신은 그것이인지 모른다 FOO<newline>BAR(환경 변수 export -p, 대부분의 포탄 보여 볼 것 env $'FOO\nBAR=test' awk 'BEGIN{for (v in ENVIRON) print v}') 또는 모두 FOOBAR환경 변수입니다.
Stéphane Chazelas

GNU awk는 자체 환경 ( AWKPATHAWKLIBPATH내 시스템) 의 환경 변수를 설정합니다.
Stéphane Chazelas

@ StéphaneChazelas-re : var name에 포함 된 개행 문자-동의-쉘 코드로 방어하기가 어렵습니다. 다시 : AWKPATH 및 AWKLIBPATH 오염, 나는 교활한 삽입도 발견했습니다. bsd awk가 아니라 gnu awk입니다.
Juan

0

나는 간단한 것을 좋아합니다. 이것은 POSIX 시스템에서 작동합니다 :

printenv | sed 's;=.*;;' | sort
HOME
HOSTNAME
PATH
PWD
SHLVL
TERM

5
export AAA=$'multi\nBBB=line'
roaima

@todd_dsm-둘 이상의 줄에 걸쳐있는 값을 갖는 환경 변수 (예 : TERMCAP-screen (1) 세션, IIRC에있을 때 표시됨)에 대해 실패합니다. 따라서이 답변은 원래 질문에 설명 된 요구 사항을 충족하지 않습니다. 나는 또한 간단한 것을 좋아하지만 이것은 일반적으로 작동하지 않습니다.
Juan

원래 게시물에서 편집 한 tidbit는 bash에서 흥미로 웠습니다 compgen -e. 휴대용 스크립팅에는 도움이되지 않지만 (예 : bash를 사용할 수없는 경우) 흥미 롭습니다.
Juan

그냥 궁금해서 왜 bourne (posix) 쉘로 자신을 제한합니까? posix 호환은 훌륭하지만 그 추구에서 많은 기능을 잃어 버립니다. bash와 이식 가능하며 posix와 호환되지 않을 수 있습니다. 그것은 GNU 제품군의 일부입니다.
todd_dsm

dash데비안에서 사용하면 위의 명령으로 동일한 결과 printenv | sed 's;*=.;;' | sort를 얻 거나 수정 하여 값을 얻습니다. 변수를 내보내고 yo위에 첫 번째 주석을 지정했습니다. 여러 줄로 예상대로 인쇄되었습니다. 당신이 겪고있는 것을 확실하지 않지만 잘린 출력이 없어야합니다. 쉘에서 명령을 실행하십시오. 출력이 무엇이든 작동 방법이 있습니다. 절두를 기대하지 마십시오. 그런 다음 TERMCAP / screen / iirc의 맥락에서; 동일해야합니다. 출력이 일치하지 않으면 해당 프로그램 중 하나에 문제가있을 수 있습니다.
todd_dsm
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.