Bash'deki betiğimde birçok değişken var ve bunları dosyaya kaydetmek için bir şeyler yapmam gerekiyor. Sorum, komut dosyamda bildirilen tüm değişkenleri nasıl listeleyeceğim ve şöyle bir liste alacağım:
VARIABLE1=abc
VARIABLE2=def
VARIABLE3=ghi
Yanıtlar:
set
değişkenlerin çıktısını alacak, ne yazık ki aynı zamanda işlevlerin tanımladığı çıktıları da verecektir.
Neyse ki POSIX modu yalnızca değişkenleri çıkarır:
( set -o posix ; set ) | less
İçin Boru less
Seçenekleri istediğiniz yere veya yönlendirme.
Dolayısıyla, yalnızca komut dosyasında açıklanan değişkenleri almak için:
( 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
(Ya da en azından buna dayalı bir şey :-))
VARS="`set -o posix ; set`"; source script; SCRIPT_VARS="`grep -vFe "$VARS" <<<"$(set -o posix ; set)" | grep -v ^VARS=`"; unset VARS;
. Bu ayrıca değişkenleri kaydetmeye hazır bir biçimde çıkarır. Liste, komut dosyasının değiştirdiği değişkenleri içerecektir (bunun istenip istenmediğine bağlıdır)
source
istiyorsanız, bunu çıktısı ile yapabilmelisiniz declare -p
.
before=$(set -o posix; set); dosomestuff; diff <(echo "$before") <(set -o posix; set)
compgen -v
Yerel olanlar dahil tüm değişkenleri listeler. Ben öğrendim adı belirli bir düzenle eşleşen değişkenlerin alın listesinde ve kullanmış senaryoma .
compgen -v
yerel olarak ayarlanmayan global değişkenleri de listeler. Bunun uzun süredir devam eden bir hata mı yoksa istenen davranış mı olduğundan emin değilim.
for i in _ {a..z} {A..Z}; do eval "echo \${!$i@}" ; done | xargs printf "%s\n"
Bu, tüm kabuk değişken adlarını yazdırmalıdır. Hangi değişkenlerin yeni olduğunu ayırt etmek için (diğer cevaplarda açıklandığı gibi) "set" ile olduğu gibi dosyanızı kaynaklamadan önce ve sonra bir liste alabilirsiniz. Ancak, diff ile bu tür filtrelemenin, ihtiyacınız olan ancak dosyanızı tedarik etmeden önce mevcut olan bazı değişkenleri filtreleyebileceğini unutmayın.
Sizin durumunuzda, değişkenlerinizin adlarının "DEĞİŞKEN" ile başladığını biliyorsanız, o zaman komut dosyanızı kaynaklayabilir ve şunları yapabilirsiniz:
for var in ${!VARIABLE@}; do
printf "%s%q\n" "$var=" "${!var}"
done
GÜNCELLEME: Saf BASH çözümü için (harici komut kullanılmaz):
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})"
Yukarıdaki cevaplardan bazılarına dayanarak, bu benim için çalıştı:
before=$(set -o posix; set | sort);
kaynak dosya :
comm -13 <(printf %s "$before") <(set -o posix; set | sort | uniq)
Sonradan işlem yapabiliyorsanız, (daha önce bahsedildiği gibi) set
betiğinizin başına ve sonuna (her biri farklı bir dosyaya) bir çağrı yapabilir ve iki dosyada bir fark yapabilirsiniz. Bunun hala biraz gürültü içereceğini anlayın.
Bunu programlı olarak da yapabilirsiniz. Çıktıyı yalnızca mevcut kapsamınızla sınırlamak için, değişken oluşturmaya bir sarmalayıcı uygulamanız gerekir. Örneğin
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
Hangi verim
VAR1=abc
VAR2=bcd
VAR3=cde
İşte @ GinkgoFr yanıtına benzer, ancak @Tino veya @DejayClayton tarafından tanımlanan sorunlar olmadan ve @ DouglasLeeder'ın akıllı bitinden daha sağlam set -o posix
:
+ function SOLUTION() { (set +o posix; set) | sed -ne '/^\w\+=/!q; p;'; }
Aradaki fark, bu çözümün ilk değişken olmayan rapordan sonra DURMASI, örn. set
BTW: "Tino" sorunu çözüldü. POSIX kapatılır ve işlevleri tarafından bildirilen rağmen set
, sed ...
çözümün kısmı sadece (örneğin aracılığıyla değişken raporlar verir VAR=VALUE
çizgiler). Özellikle, A2
yok değil spuriously çıktı dönüştürebilmek.
+ function a() { echo $'\nA2=B'; }; A0=000; A9=999;
+ SOLUTION | grep '^A[0-9]='
A0=000
A9=999
VE: "DejayClayton" sorunu (değişken değerler gömülü yeni satırlar do çözüldü değil çıktıyı bozmak - her VAR=VALUE
tek çıkış hattı almak):
+ A1=$'111\nA2=222'; A0=000; A9=999;
+ SOLUTION | grep '^A[0-9]='
A0=000
A1=$'111\nA2=222'
A9=999
NOT: @DouglasLeeder tarafından sağlanan çözüm, "DejayClayton" sorunundan muzdariptir (gömülü satırsonu değerleri). Aşağıda A1
yanlış ve A2
hiç gösterilmemelidir.
$ A1=$'111\nA2=222'; A0=000; A9=999; (set -o posix; set) | grep '^A[0-9]='
A0=000
A1='111
A2=222'
A9=999
SONUNDA: Konuların versiyonunu düşünmüyorum bash
, ama olabilir. Test / geliştirmemi bunun üzerinde yaptım:
$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-msys)
POST-SCRIPT: OP'ye verilen diğer bazı yanıtlar göz önüne alındığında , değer içindeki satırları set
her zaman dönüştürdüğünden <% 100 eminim \n
, bu çözüm "DejayClayton" sorununu önlemek için buna dayanıyor. Belki de bu modern bir davranış? Veya bir derleme zamanı varyasyonu? Veya bir set -o
veya shopt
seçenek ayarı? Eğer siz böyle varyasyonların biliyoruz Yorum eklemek ... Lütfen
Güvenlik açısından, ya @ akostadinov'un yanıtı ya da @ JuvenXu'nun yanıtı , set
aşağıdaki olası güvenlik açığı nedeniyle komutun yapılandırılmamış çıktısına güvenmeye tercih edilir :
#!/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
Yukarıdaki işlev , komut dosyasının etkileşimli olup olmadığını belirlemek için değişkenin varlığını kontrol etmek için doLogic
kullanır (bu hedefi gerçekleştirmenin en iyi yolu olup olmadığını boşverin; bu sadece bir örnektir.)set
PS1
Bununla birlikte, çıktısı set
yapılandırılmamıştır, bu da bir satırsonu içeren herhangi bir değişkenin sonuçları tamamen kirletebileceği anlamına gelir.
Bu, elbette, potansiyel bir güvenlik riskidir. Bunun yerine, ya Bash'in dolaylı değişken adı genişletme desteğini ya da compgen -v
.
Şunu deneyin: set | egrep "^\w+="
(ile veya olmadan| less
borulu borusuz)
Önerilen ilk çözüm ( set -o posix ; set ) | less
işe yarıyor ancak bir dezavantajı var: kontrol kodlarını terminale iletiyor, böylece düzgün görüntülenmiyorlar. Örneğin, bir değişken varsa (muhtemelen)IFS=$' \t\n'
, şunu görebiliriz:
IFS='
'
…yerine.
Benim egrep
çözümüm bunu (ve sonunda diğer benzerlerini) düzgün bir şekilde gösteriyor.
bash -c $'a() { echo "\nA=B"; }; unset A; set | egrep "^\w+="' | grep ^A
görüntüler A=B"
-> Başarısız!
Muhtemelen cevabı bir süre önce çaldım ... Zaten biraz farklı bir işlev olarak:
##
# 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"
}
Bunu yapmanın basit yolu , komut dosyanızı çalıştırmadan önce sistem ortamı değişkenlerini ayarlayarak sıkı sıkı modunu kullanmak ve yalnızca komut dosyanızı sıralamak için diff kullanmaktır:
# 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
Betiğinizin değişkenlerini artık /tmp/script_vars.log'da alabilirsiniz. Ya da en azından buna dayalı bir şey!
Partiye biraz geç ama işte başka bir öneri:
#!/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'
Fark + sed boru hattı komut satırı istenen biçiminde tüm komut tanımlanmış değişkenleri (OP yayınının belirtildiği gibi) verir:
VARIABLE1=a
VARIABLE2=b
VARIABLE3=c
-o posix
Şimdi bir fark ile güzel çağrı yalnızca değişkenleri içerecektir.