Uyarı: Bu çözümlerden herhangi birinde, komut dosyasında kabuk kodu olarak yürütülecekleri için veri dosyalarının bütünlüğünün güvende olduğuna güvendiğinizi bilmeniz gerekir. Onları güvence altına almak, komut dosyanızın güvenliği için çok önemlidir!
Bir veya daha fazla değişkeni serileştirmek için basit satır içi uygulama
Evet, hem bash hem de zsh'de, bir değişkenin içeriğini typeset
yerleşik ve -p
argümanı kullanarak alması kolay bir şekilde serileştirebilirsiniz . Çıktı biçimi, source
çıktılarınızı geri almak için çıktıyı kolayca alabileceğiniz şekildedir.
# You have variable(s) $FOO and $BAR already with your stuff
typeset -p FOO BAR > ./serialized_data.sh
Eşyalarınızı daha sonra komut dosyanızda veya başka bir komut dosyasında tamamen geri alabilirsiniz:
# Load up the serialized data back into the current shell
source serialized_data.sh
Bu, farklı kabuklar arasında veri aktarımı da dahil olmak üzere bash, zsh ve ksh için çalışacaktır. Bash bunu yerleşik declare
işlevine çevirecek , zsh ise bunu uygulayacak typeset
ancak typeset
bash'ın burada ksh uyumluluğu için kullandığımız her iki şekilde çalışması için bir takma adı olduğu için .
İşlevleri kullanarak daha karmaşık genelleştirilmiş uygulama
Yukarıdaki uygulama gerçekten basittir, ancak sık sık ararsanız, bunu kolaylaştırmak için kendinize bir yardımcı program işlevi vermek isteyebilirsiniz. Ayrıca, yukarıdaki özel işlevlerin içine dahil etmeye çalışırsanız, değişken kapsam belirleme sorunlarıyla karşılaşırsınız. Bu sürüm bu sorunları ortadan kaldırmalıdır.
Bunların hepsine dikkat edin, bash / zsh çapraz uyumluluğunu korumak için her iki durumu da düzelteceğiz typeset
ve declare
bu nedenle kodun kabuklardan birinde veya her ikisinde de çalışması gerekir. Bu, yalnızca bir kabuk veya diğeri için bunu yapıyorsanız ortadan kaldırılabilecek bazı toplu ve karışıklık ekler.
Bunun için işlevlerin kullanılmasıyla ilgili ana sorun (veya kodu diğer işlevlere dahil etmek), typeset
işlevin, bir işlevin içinden bir komut dosyasına geri kaynaklandığında, genel bir değişken yerine yerel bir değişken oluşturmayı varsayılan olarak kod üretmesidir.
Bu, birkaç hack'ten biriyle düzeltilebilir. Bunu düzeltmek için ilk denemem , oluşturulan kod geri kaynaklandığında genel bir değişkeni tanımlamak sed
için -g
bayrağı eklemek için serialize sürecinin çıktısını ayrıştırmaktı .
serialize() {
typeset -p "$1" | sed -E '0,/^(typeset|declare)/{s/ / -g /}' > "./serialized_$1.sh"
}
deserialize() {
source "./serialized_$1.sh"
}
Korkak sed
ifadenin yalnızca 'yazı kümesi' veya 'deklarasyon' kelimelerinin ilk oluşumuyla eşleşeceğini ve -g
ilk argüman olarak ekleneceğini unutmayın . Stéphane Chazelas'ın yorumlarda doğru bir şekilde işaret ettiği için sadece ilk tekrarla eşleşmek gerekir, aksi takdirde serileştirilmiş dizenin, kelimenin tam anlamıyla yeni satırlar içerdiği ve ardından bildiri veya yazı kümesi içerdiği durumlarla da eşleşir.
İlk ayrıştırma sahte pas'ımı düzeltmenin yanı sıra , Stéphane de bunu kesmek için daha az kırılgan bir yol önerdi , bu da sadece dizeleri ayrıştırmayla ilgili sorunları atmakla kalmadı, aynı zamanda eylemleri yeniden tanımlamak için bir sarma işlevi kullanarak ek işlevsellik eklemek için yararlı bir kanca olabilir. Bu, beyan veya dizgi komutlarıyla başka bir oyun oynamadığınızı varsayar, ancak bu tekniğin kendi işlevinizin bir parçası olarak veya bu işlevi eklediğiniz bir durumda uygulanması daha kolay olacaktır. yazılan verilerin ve -g
bayrağın eklenip eklenmediğinin kontrolü sizde değildi . Takma adlarla da benzer bir şey yapılabilir, bkz. Gilles'in bir uygulama cevabı .
Sonucu daha da kullanışlı hale getirmek için, bağımsız değişken dizisindeki her kelimenin bir değişken adı olduğunu varsayarak işlevlerimize aktarılan birden çok değişken üzerinde yineleme yapabiliriz. Sonuç şöyle olur:
serialize() {
for var in $@; do
typeset -p "$var" > "./serialized_$var.sh"
done
}
deserialize() {
declare() { builtin declare -g "$@"; }
typeset() { builtin typeset -g "$@"; }
for var in $@; do
source "./serialized_$var.sh"
done
unset -f declare typeset
}
Her iki çözümde de kullanım şöyle görünür:
# Load some test data into variables
FOO=(an array or something)
BAR=$(uptime)
# Save it out to our serialized data files
serialize FOO BAR
# For testing purposes unset the variables to we know if it worked
unset FOO BAR
# Load the data back in from out data files
deserialize FOO BAR
echo "FOO: $FOO\nBAR: $BAR"