Programing

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

crosscheck 2020. 9. 16. 07:08
반응형

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"

모든 쉘 변수 이름을 인쇄해야합니다. 어떤 변수가 새로운 것인지 비교하기 위해 "set"을 사용하는 것처럼 파일을 소싱하기 전후에 목록을 얻을 수 있습니다 (다른 답변에서 설명 됨). 그러나 diff를 사용한 이러한 필터링은 필요하지만 파일을 소싱하기 전에 존재했던 일부 변수를 필터링 할 수 있음을 명심하십시오.

귀하의 경우 변수 이름이 "VARIABLE"로 시작하는 것을 알고 있다면 스크립트를 소싱하고 다음을 수행 할 수 있습니다.

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스크립트의 시작과 끝에 (각각 다른 파일에 대해) 호출하고 두 파일에 대해 diff를 수행 할 수 있습니다. 여기에는 여전히 약간의 소음이 포함되어 있음을 인식하십시오.

프로그래밍 방식으로도 수행 할 수 있습니다. 출력을 현재 범위로만 제한하려면 변수 생성에 대한 래퍼를 구현해야합니다. 예를 들면

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

다음은 @GinkgoFr 답변과 비슷하지만 @Tino 또는 @DejayClayton으로 식별되는 문제가 없으며 @DouglasLeeder의 영리한 set -o posix비트 보다 더 강력합니다 .

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

차이점은이 솔루션이 첫 번째 비 변수 보고서 (예 : set

BTW: The "Tino" problem is solved. Even though POSIX is turned off and functions are reported by set, the sed ... portion of the solution only allows variable reports through (e.g. VAR=VALUE lines). In particular, the A2 does not spuriously make it into the output.

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

AND: The "DejayClayton" problem is solved (embedded newlines in variable values do not disrupt the output - each VAR=VALUE get a single output line):

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

NOTE: The solution provided by @DouglasLeeder suffers from the "DejayClayton" problem (values with embedded newlines). Below, the A1 is wrong and A2 should not show at all.

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

FINALLY: I don't think the version of bash matters, but it might. I did my testing / developing on this one:

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

POST-SCRIPT: Given some of the other responses to the OP, I'm left < 100% sure that set always converts newlines within the value to \n, which this solution relies upon to avoid the "DejayClayton" problem. Perhaps that's a modern behavior? Or a compile-time variation? Or a set -o or shopt option setting? If you know of such variations, please add a comment...


Try using a script (lets call it "ls_vars"):

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

chmod +x it, and:

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

From a security perspective, either @akostadinov's answer or @JuvenXu's answer is preferable to relying upon the unstructured output of the set command, due to the following potential security flaw:

#!/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

The above function doLogic uses set to check for the presence of variable PS1 to determine if the script is interactive or not (never mind if this is the best way to accomplish that goal; this is just an example.)

However, the output of set is unstructured, which means that any variable that contains a newline can totally contaminate the results.

This, of course, is a potential security risk. Instead, use either Bash's support for indirect variable name expansion, or compgen -v.


I probably have stolen the answer while ago ... anyway slightly different as a 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"
    } 

The printenv command:

printenv prints all environment variables along with their values.

Good Luck...


Try this : set | egrep "^\w+=" (with or without the | less piping)

The first proposed solution, ( set -o posix ; set ) | less, works but has a drawback: it transmits control codes to the terminal, so they are not displayed properly. So for example, if there is (likely) a IFS=$' \t\n' variable, we can see:

IFS='
'

…instead.

My egrep solution displays this (and eventually other similars ones) properly.

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

반응형