चेतावनी: इनमें से किसी भी समाधान के साथ, आपको यह जानने की आवश्यकता है कि आप सुरक्षित होने के लिए डेटा फ़ाइलों की अखंडता पर भरोसा कर रहे हैं क्योंकि वे आपकी स्क्रिप्ट में शेल कोड के रूप में निष्पादित होंगे। उन्हें सुरक्षित करना आपकी स्क्रिप्ट की सुरक्षा के लिए सर्वोपरि है!
एक या अधिक चरों को क्रमबद्ध करने के लिए सरल इनलाइन कार्यान्वयन
हां, बाश और zsh दोनों में, आप एक चर की सामग्री को इस तरह से अनुक्रमित कर सकते हैं जो बिलिन typeset
और -p
तर्क का उपयोग करके पुनः प्राप्त करना आसान है । आउटपुट स्वरूप ऐसा है कि आप केवल source
अपना सामान वापस पाने के लिए आउटपुट कर सकते हैं।
# You have variable(s) $FOO and $BAR already with your stuff
typeset -p FOO BAR > ./serialized_data.sh
आप अपना सामान इस तरह से बाद में अपनी स्क्रिप्ट में या किसी अन्य स्क्रिप्ट में पूरी तरह से वापस पा सकते हैं:
# Load up the serialized data back into the current shell
source serialized_data.sh
यह बैश, zsh और ksh के लिए काम करेगा जिसमें विभिन्न गोले के बीच डेटा पास करना शामिल है। बाश इसे अपने declare
बिल्टइन फंक्शन में ट्रांसलेट करेगा जबकि zsh इसके साथ इम्प्लीमेंट करता है typeset
लेकिन बैश के पास इस बात के लिए एक उपनाम है कि हम typeset
ksh कम्पैटिबिलिटी के लिए यहां इस्तेमाल करें।
कार्यों का उपयोग करके अधिक जटिल सामान्यीकृत कार्यान्वयन
उपरोक्त कार्यान्वयन वास्तव में सरल है, लेकिन यदि आप इसे अक्सर कहते हैं, तो आप इसे आसान बनाने के लिए अपने आप को एक उपयोगिता फ़ंक्शन दे सकते हैं। इसके अतिरिक्त यदि आप कभी भी उपरोक्त कस्टम फ़ंक्शंस को शामिल करने का प्रयास करते हैं तो आप चर स्कोपिंग के साथ समस्याओं में चलेंगे। इस संस्करण को उन मुद्दों को समाप्त करना चाहिए।
इन सभी के लिए ध्यान दें, बैश / zsh क्रॉस-अनुकूलता बनाए रखने के लिए हम दोनों मामलों को ठीक कर रहे होंगे typeset
और declare
इसलिए कोड को दोनों या दोनों गोले में काम करना चाहिए। यह कुछ बल्क और मेस जोड़ता है, जिन्हें यदि आप केवल एक शेल या दूसरे के लिए कर रहे हैं, तो इसे समाप्त किया जा सकता है।
इसके लिए फ़ंक्शंस का उपयोग करने में (या अन्य फ़ंक्शंस में कोड सहित) मुख्य समस्या यह है कि typeset
फ़ंक्शन कोड उत्पन्न करता है, जब किसी फ़ंक्शन के अंदर से स्क्रिप्ट में वापस आ जाता है, एक वैश्विक एक के बजाय एक स्थानीय चर बनाने के लिए चूक करता है।
यह कई हैक्स में से एक के साथ तय किया जा सकता है। इसे ठीक करने का मेरा प्रारंभिक प्रयास ध्वज sed
को जोड़ने के माध्यम से क्रमबद्ध प्रक्रिया के उत्पादन को पार्स करने के लिए था, -g
इसलिए बनाया गया कोड वैश्विक वैरिएबल को परिभाषित करता है, जब इसे वापस भेजा जाता है।
serialize() {
typeset -p "$1" | sed -E '0,/^(typeset|declare)/{s/ / -g /}' > "./serialized_$1.sh"
}
deserialize() {
source "./serialized_$1.sh"
}
ध्यान दें कि कायरता sed
अभिव्यक्ति केवल 'टाइपसेट' या 'घोषित' की पहली घटना से मेल खाना है और -g
पहले तर्क के रूप में जोड़ना है। यह केवल पहली घटना से मेल खाने के लिए आवश्यक है क्योंकि, स्टीफन चेज़ेलस ने ठीक ही टिप्पणियों में बताया है, अन्यथा यह उन मामलों से भी मेल खाएगा जहां धारावाहिक रूप से स्ट्रिंग में शाब्दिक नए शब्द शामिल हैं, जिसके बाद शब्द घोषित या टाइपसेट होता है।
मेरे प्रारंभिक पार्सिंग फ़ॉक्स पेस को ठीक करने के अलावा , स्टीफ़ेन ने इसे हैक करने के लिए एक कम भंगुर तरीका भी सुझाया , जो न केवल साइड को स्ट्रिंग्स को पार्स करने के साथ मुद्दों को उठाता है, बल्कि क्रियाओं को फिर से परिभाषित करने के लिए रैपर फ़ंक्शन का उपयोग करके अतिरिक्त कार्यक्षमता जोड़ने के लिए एक उपयोगी हुक हो सकता है। जब डेटा वापस सोर्सिंग में लिया जाता है। यह मान लेता है कि आप घोषित या टाइपसेट कमांड के साथ कोई अन्य गेम नहीं खेल रहे हैं, लेकिन इस तकनीक को ऐसी स्थिति में लागू करना आसान होगा जहां आप इस कार्यक्षमता को अपने स्वयं के किसी अन्य फ़ंक्शन के हिस्से के रूप में शामिल कर रहे थे। आप लिखे गए डेटा के नियंत्रण में नहीं थे और इसमें -g
ध्वज जोड़ा गया था या नहीं । कुछ ऐसा ही उपनामों के साथ भी किया जा सकता है, कार्यान्वयन के लिए गिल्स का जवाब देखें ।
परिणाम को और अधिक उपयोगी बनाने के लिए, हम यह मानकर कि हमारे शब्द तर्क सरणी में प्रत्येक शब्द एक चर नाम है, कई कार्यों पर पारित कर सकते हैं। परिणाम कुछ इस तरह हो जाता है:
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
}
या तो समाधान के साथ, उपयोग इस तरह दिखेगा:
# 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"