programing

bash에서 스크립트에 선언된 변수를 나열하는 방법은 무엇입니까?

bestprogram 2023. 5. 17. 23:34

bash에서 스크립트에 선언된 변수를 나열하는 방법은 무엇입니까?

bash에 있는 제 스크립트에는 변수가 너무 많아서 파일에 저장할 수 있는 것을 만들어야 합니다.내 질문은 스크립트에 선언된 모든 변수를 나열하고 다음과 같은 목록을 가져오는 방법입니다.

VARIABLE1=abc
VARIABLE2=def
VARIABLE3=ghi

set변수를 출력하지만 안타깝게도 정의된 함수도 출력합니다.

다행히 POSIX 모드는 다음 변수만 출력합니다.

( set -o posix ; set ) | less

과 결대상 연결less또는 옵션을 원하는 위치로 리디렉션합니다.

변수를 스크립트로만 선언하려면 다음과 같이 하십시오.

( set -o posix ; set ) >/tmp/variables.before
source script
( set -o posix ; set ) >/tmp/variables.after
diff /tmp/variables.before /tmp/variables.after
rm /tmp/variables.before /tmp/variables.after

(또는 적어도 그것을 기반으로 한 무언가 :-)

compgen -v

로컬 변수를 포함한 모든 변수가 나열됩니다.이름이 특정 패턴과 일치하는 변수 목록 가져오기에서 학습하여 스크립트에 사용했습니다.

for i in _ {a..z} {A..Z}; do eval "echo \${!$i@}" ; done | xargs printf "%s\n"

모든 셸 변수 이름을 인쇄해야 합니다.파일을 소싱하기 전과 후에 어떤 변수가 새로운지 "설정"과 마찬가지로 목록을 얻을 수 있습니다(다른 답변 참조).그러나 diff를 사용한 이러한 필터링은 파일을 소스하기 전에 필요하지만 존재하는 일부 변수를 필터링할 수 있습니다.

이 경우 변수 이름이 "VARIVEL"로 시작하는 경우 스크립트를 소스화하여 다음 작업을 수행할 수 있습니다.

for var in ${!VARIABLE@}; do
   printf "%s%q\n" "$var=" "${!var}"
done

업데이트: 순수 BASH 솔루션의 경우(외부 명령 사용 안 함):

for i in _ {a..z} {A..Z}; do
   for var in `eval echo "\\${!$i@}"`; do
      echo $var
      # you can test if $var matches some criteria and put it in the file or ignore
   done 
done

위의 답변 중 몇 가지를 바탕으로, 이것은 저에게 효과가 있었습니다.

before=$(set -o posix; set | sort);

원본 파일:

comm -13 <(printf %s "$before") <(set -o posix; set | sort | uniq) 

만약 당신이 (이미 언급한 것처럼) 후처리를 할 수 있다면, 당신은 그냥 다음을 배치할 수 있습니다.set스크립트의 시작과 끝에 각각 다른 파일을 호출하고 두 파일에 대해 다른 작업을 수행합니다.여기에는 여전히 약간의 소음이 포함되어 있습니다.

프로그램적으로 이 작업을 수행할 수도 있습니다.출력을 현재 범위로만 제한하려면 변수 생성 래퍼를 구현해야 합니다.예를들면

store() {
    export ${1}="${*:2}"
    [[ ${STORED} =~ "(^| )${1}($| )" ]] || STORED="${STORED} ${1}"
}

store VAR1 abc
store VAR2 bcd
store VAR3 cde

for i in ${STORED}; do
    echo "${i}=${!i}"
done

산출물

VAR1=abc
VAR2=bcd
VAR3=cde

파티에 조금 늦었지만 다른 제안이 있습니다.

#!/bin/bash

set_before=$( set -o posix; set | sed -e '/^_=*/d' )

# create/set some variables
VARIABLE1=a
VARIABLE2=b
VARIABLE3=c

set_after=$( set -o posix; unset set_before; set | sed -e '/^_=/d' )
diff  <(echo "$set_before") <(echo "$set_after") | sed -e 's/^> //' -e '/^[[:digit:]].*/d'

diff+sed 파이프라인 명령줄은 OP의 게시물에 지정된 대로 원하는 형식으로 모든 스크립트 정의 변수를 출력합니다.

VARIABLE1=a
VARIABLE2=b
VARIABLE3=c

답과 @ 또는 의해 @ @GinkoFr @Tino @DujayClayton @Douglas @보다 더 합니다.한 리더의리함영.set -o posix슬롯:

+ function SOLUTION() { (set +o posix; set) | sed -ne '/^\w\+=/!q; p;'; }

이가 없는 첫 보고서를 들어 차: 된▁reported예▁by▁function▁first,▁the▁stops▁reportable▁solution▁this▁the▁that▁non▁first-vari다것▁after▁diffe이▁e니입는rence▁isg차후다중▁the(이에 의해 보고된 첫 번째 함수가 보고된 후에 의해 중지된다는 것입니다.set

BTW: "티노" 문제는 해결되었습니다.이 POSIX에 의해 에도 POSIX에 보고됩니다.set,sed ... ▁through(▁()를 통해서만 가변 합니다.VAR=VALUE선)을 선택합니다. 히특은,A2출력에 박차를 가하지 않습니다.

+ function a() { echo $'\nA2=B'; }; A0=000; A9=999; 
+ SOLUTION | grep '^A[0-9]='
A0=000
A9=999

AND: "DejayClayton" 문제가 해결되었습니다(변수 값에 포함된 새 줄은 출력을 방해하지 않습니다 - 각각VAR=VALUE단일 출력 라인 가져오기):

+ A1=$'111\nA2=222'; A0=000; A9=999; 
+ SOLUTION | grep '^A[0-9]='
A0=000
A1=$'111\nA2=222'
A9=999

@: @Douglas에서 하는 은 "포함된 값) 있습니다.Leeder는 "DejayClayton"(새 줄이 포함된 값) 문제를 겪고 있습니다. 에래아,A1 틀습니다렸다.A2보여주면 안 돼요.

$ A1=$'111\nA2=222'; A0=000; A9=999; (set -o posix; set) | grep '^A[0-9]='
A0=000
A1='111
A2=222'
A9=999

마지막으로:의 버전은 아닌 것 같습니다.bash중요하지만 그럴 수도 있습니다. 테스트: 스트개수/발을습니다행테했개다

$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-msys)

, POST-SCRIPT: OP에 대해 100%>, < % 확신합니다.set 항상 값 내의 새 줄을 다음으로 변환합니다.\n이 솔루션은 "Dejay Clayton" 문제를 피하기 위해 사용됩니다.그게 현대적인 행동일까요?아니면 컴파일 시간 변화? 라오.set -o또는shopt옵션 설정?그러한 변형을 알고 있다면 코멘트를 추가해 주십시오...

정적 값이 있는 변수 목록을 인쇄하는 데만 관심이 있다면(예: 이 경우 확장이 작동하지 않음) 다른 옵션은 정적 변수 정의 블록이 어디에 있는지 알려주는 시작 및 끝 마커를 파일에 추가하는 것입니다.

#!/bin/bash

# some code

# region variables
VAR1=FOO
VAR2=BAR
# endregion

# more code

그러면 파일의 그 부분만 인쇄하면 됩니다.

제가 생각해 낸 것은 다음과 같습니다.

function show_configuration() {
   local START_LINE=$(( $(< "$0" grep -m 1 -n "region variables" | cut -d: -f1) + 1 ))
   local END_LINE=$(( $(< "$0" grep -m 1 -n "endregion" | cut -d: -f1) - 1 ))
   < "$0" awk "${START_LINE} <= NR && NR <= ${END_LINE}"
}

변수 이 이 가 있는하십시오. 할 동 파 있 사 로 므 으 수 있 습 니 다 에 일 한 일 는 가 록 함 수 이 이 있 ▁first 니 다 습 ▁use$0파일 내용에 액세스할 수 있습니다.

코드의 다른 영역을 구분하기 위해 "지역" 마커를 사용합니다.그래서 저는 간단하게grep"선택된" 영역 마커의 경우(첫 번째 일치:grep -m 1및 ) 및셋grep 번호에 접두사를 붙입니다.grep -n는 매치 출력에서 줄은 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .:이나 뺄셈을 .1마커가 출력물의 일부가 되는 것을 원하지 않기 때문입니다.

그 이제사는파범일인쇄면려하위를용을 사용합니다.awk라인 번호 조건을 사용합니다.

스크립트를 사용해 보십시오("ls_vars"라고 부릅니다).

  #!/bin/bash
  set -a
  env > /tmp/a
  source $1
  env > /tmp/b
  diff /tmp/{a,b} | sed -ne 's/^> //p'

chmod +xit, 그리고:

  ls_vars your-script.sh > vars.files.save

보안 측면에서 볼 때, @akostadinov의 답변이나 @YoungXu의 답변 중 하나가 가상 머신의 비정형 출력에 의존하는 것보다 더 좋습니다.set다음과 같은 잠재적인 보안 결함으로 인해 명령이 실행됩니다.

#!/bin/bash

function doLogic()
{
    local COMMAND="${1}"
    if ( set -o posix; set | grep -q '^PS1=' )
    then
        echo 'Script is interactive'
    else
        echo 'Script is NOT interactive'
    fi
}

doLogic 'hello'   # Script is NOT interactive
doLogic $'\nPS1=' # Script is interactive

의 함수는 다음과 .doLogic사용하다set변수가 합니다.PS1스크립트가 대화형인지 여부를 확인합니다(이 방법이 해당 목표를 달성하는 가장 좋은 방법인지는 신경쓰지 마십시오. 예에 불과합니다.).

그나, 출은의 set비정형이므로 새 줄이 포함된 변수가 결과를 완전히 오염시킬 수 있습니다.

물론 이것은 잠재적인 보안 위험입니다.확장을 하거나 Bash의 지원을 합니다.compgen -v.

사용해 보십시오.set | egrep "^\w+="(| less배관)

번째 해결책인 첫번째제해은책결된안,,,( set -o posix ; set ) | less는 작동하지만 터미널에 제어 코드를 전송하여 제대로 표시되지 않는 단점이 있습니다.그래서 예를 들어, 만약 (가능성이) 있다면,IFS=$' \t\n'변수, 우리는 볼 수 있습니다:

IFS='
'

…어쨌든.

나의egrep솔루션은 이를 올바르게 표시하고 최종적으로 다른 유사한 항목도 표시합니다.

제가 아마 아까 답을 훔쳤을 거예요...어쨌든 func로서 약간 다릅니다.

    ##
    # usage source bin/nps-bash-util-funcs
    # doEchoVars
    doEchoVars(){

        # if the tmp dir does not exist
        test -z ${tmp_dir} && \
        export tmp_dir="$(cd "$(dirname $0)/../../.."; pwd)""/dat/log/.tmp.$$" && \
        mkdir -p "$tmp_dir" && \
        ( set -o posix ; set )| sort >"$tmp_dir/.vars.before"


        ( set -o posix ; set ) | sort >"$tmp_dir/.vars.after"
        cmd="$(comm -3 $tmp_dir/.vars.before $tmp_dir/.vars.after | perl -ne 's#\s+##g;print "\n $_ "' )"
        echo -e "$cmd"
    } 

printenv명령:

printenv 인쇄합니다. 인.environment variables그들의 가치관과 함께.

행운을 빕니다...

간단한 방법은 스크립트를 실행하기 전에 시스템 환경 변수를 설정하여 bash strict 모드를 사용하고 diff를 사용하여 스크립트의 변수만 정렬하는 것입니다.

# Add this line at the top of your script :
set > /tmp/old_vars.log

# Add this line at the end of your script :
set > /tmp/new_vars.log

# Alternatively you can remove unwanted variables with grep (e.g., passwords) :
set | grep -v "PASSWORD1=\|PASSWORD2=\|PASSWORD3=" > /tmp/new_vars.log

# Now you can compare to sort variables of your script :
diff /tmp/old_vars.log /tmp/new_vars.log | grep "^>" > /tmp/script_vars.log

이제 /tmp/script_vars.log에서 스크립트의 변수를 검색할 수 있습니다.아니면 적어도 그것을 기반으로 한 무언가!

TL;DR

포함:typeset -m <GLOBPATH>

$ VARIABLE1=abc
$ VARIABLE2=def
$ VARIABLE3=ghi
$ noglob typeset -m VARIABLE*
VARIABLE1=abc
VARIABLE2=def
VARIABLE3=ghi

대 한 문에 대한 설명서.typeset에서 찾을 수 있습니다.man zshbuiltins또는man zshall.

언급URL : https://stackoverflow.com/questions/1305237/how-to-list-variables-declared-in-script-in-bash