답변:
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
(또는 적어도 그것을 기반으로 한 것 :-))
VARS="`set -o posix ; set`"; source script; SCRIPT_VARS="`grep -vFe "$VARS" <<<"$(set -o posix ; set)" | grep -v ^VARS=`"; unset VARS;
. 그러면 바로 저장할 수있는 형식으로 변수도 출력됩니다. 목록이 변경 스크립트 (이것은이 바람직하다 여부 따라 다름)이라는 변수를 포함합니다
source
수 있도록하려면 declare -p
.
before=$(set -o posix; set); dosomestuff; diff <(echo "$before") <(set -o posix; set)
compgen -v
지역 변수를 포함한 모든 변수를 나열합니다. 이름이 특정 패턴과 일치하는 변수 목록 가져 오기에서 배웠고 스크립트 에서 사용했습니다 .
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
eval "printf '%q\n' $(printf ' "${!%s@}"' _ {a..z} {A..Z})"
후 처리를 할 수 있다면 (이미 언급했듯이) 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 : "티노"문제가 해결되었습니다. POSIX가 꺼져 있고 함수가에 의해보고 되더라도 솔루션 set
의 sed ...
일부는 (예 : 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
참고 : @DouglasLeeder에서 제공하는 솔루션은 "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에 대한 다른 응답 중 일부를 감안할 때 set
항상 값 내에서 줄 바꿈을으로 변환 하는 것이 100 % 미만임을 확신합니다. \n
이 솔루션은 "DejayClayton"문제를 피하기 위해 의존합니다. 아마도 그것은 현대적인 행동일까요? 아니면 컴파일 시간 변형입니까? 또는 set -o
또는 shopt
옵션 설정? 이러한 변형 을 알고 있다면 의견을 추가하십시오 ...
보안 관점에서 @akostadinov의 대답 또는 @JuvenXu의 대답 은 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
솔루션은 이것을 (그리고 결국 다른 유사한 것들) 제대로 표시합니다.
bash -c $'a() { echo "\nA=B"; }; unset A; set | egrep "^\w+="' | grep ^A
디스플레이 이기 때문에 반대 투표A=B"
-> 실패!
나는 아마 전에 대답 을 훔 쳤을 것입니다 ... 어쨌든 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"
}
이를 수행하는 간단한 방법은 스크립트를 실행하기 전에 시스템 환경 변수를 설정 하여 bash 엄격 모드 를 사용하고 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에서 스크립트의 변수를 검색 할 수 있습니다. 아니면 적어도 그것을 기반으로 한 것!
파티에 조금 늦었지만 여기에 또 다른 제안이 있습니다.
#!/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 + 나오지 파이프 라인 명령 줄은 원하는 형식의 모든 스크립트 정의 변수를 (영업 이익의 게시물에 지정된대로)를 출력한다 :
VARIABLE1=a
VARIABLE2=b
VARIABLE3=c
-o posix
이제 diff를 사용한 멋진 호출 에는 변수 만 포함됩니다.