मैंने कुछ जटिल स्क्रिप्ट्स के साथ लागू करने के लिए एक बैश लॉगिंग लाइब्रेरी लिखी है जिसे मेरी कंपनी वर्तमान में उपयोग कर रही है। मैं लॉग कॉल करते समय स्क्रिप्ट फ़ाइल नाम ($ {BASH_SOURCE}) और कॉलिंग स्क्रिप्ट के लाइन नंबर ($ {LINENO}) प्रदान करने पर डेडसेट कर रहा हूं। हालांकि, मैं पैरामीटर के रूप में इन दो चरों में पारित करने के लिए उपयोगकर्ता या स्क्रिप्ट को लागू करने पर भरोसा नहीं करना चाहता था। यदि यह सी/सी ++ था, तो मैं केवल एक मैक्रो बनाउंगा जो पैरामीटर सूची में "__FILE__" और "__LINE__" को पूर्ववत करता है।बैश पैरामीटर उद्धरण और eval
मैं अंततः इस भाग को काम करने में सक्षम था।
यहाँ प्रवेश पुस्तकालय है:
# log.sh
LOG="eval _log \${BASH_SOURCE} \${LINENO}"
_log() {
_BASH_SOURCE=`basename "${1}"` && shift
_LINENO=${1} && shift
echo "(${_BASH_SOURCE}:${_LINENO}) [email protected]"
}
और एक को लागू परीक्षण स्क्रिप्ट: यहाँ अवधारणा का एक सबूत के रूप में कुछ ज्यादा सरल सार हैं
# MyTest.sh
. ./log.sh
${LOG} "This is a log message"
# (test.sh:5) This is a log message
यह अच्छी तरह से बहुत से काम करता है (और, मैं इसे पहले काम करने के लिए रोमांचित था)। हालांकि, इसमें एक चमकदार समस्या है: उद्धरण और eval के बीच बातचीत। अगर मैं कॉल करता हूं:
${LOG} "I'm thrilled that I got this working"
# ./test.sh: eval: line 5: unexected EOF while looking for matching `''
# ./test.sh: eval: line 6: syntax error: unexpected end of file
अब, मुझे विश्वास है कि मैं समझता हूं कि यह क्यों हो रहा है। उद्धृत पैरामीटर को बरकरार रखा जाता है क्योंकि वे eval करने के लिए पारित कर रहे हैं, लेकिन उस बिंदु पर, सामग्री को परिणामस्वरूप कमांड स्ट्रिंग में रखा गया है। मुझे पता है कि मैं कुछ भागने से इसे ठीक कर सकता हूं; हालांकि, मैं वास्तव में कार्यान्वयन स्क्रिप्ट को ऐसा करने के लिए मजबूर नहीं करना चाहता हूं। इस "eval macro" क्षमता को लागू करने से पहले, मैंने उपयोगकर्ताओं को सीधे "_log" पर कॉल किया था और उन्हें वैकल्पिक रूप से "$ {LINENO} में पास करने की अनुमति दी थी।" इस कार्यान्वयन के साथ, उपरोक्त असफल कॉल (केवल उद्धृत वाक्य के साथ) ठीक काम करता है।
सबसे बुनियादी स्तर पर, सभी मैं वास्तव में चाहते हैं एक स्क्रिप्ट कॉल करने के लिए सक्षम होने के लिए के लिए है [लॉग ऑन समारोह/मैक्रो] "स्ट्रिंग विशेष characers साथ लॉग इन करने के" और जिसके परिणामस्वरूप लॉग संदेश है फ़ाइल नाम और लाइन को शामिल लॉग संदेश के बाद, कॉलिंग स्क्रिप्ट की संख्या। यदि यह संभव है, तो मुझे लगता है कि मैं बहुत करीब हूं, लेकिन अगर कुछ ऐसा है जो मुझे अनदेखा कर रहा है तो उसे एक अलग दृष्टिकोण की आवश्यकता होगी, मैं भी इसके लिए खुला हूं। मैं उपयोगकर्ताओं को उनके सभी संदेशों से बचने के लिए मजबूर नहीं कर सकता, क्योंकि इससे संभवतः वे इस पुस्तकालय का उपयोग नहीं कर पाएंगे। यह ऐसी समस्या है कि अगर मुझे इसका समाधान नहीं मिल रहा है, तो मैं संभवतः पुरानी क्षमता पर वापस आऊंगा (जिसकी आवश्यकता $ {LINENO} को फ़ंक्शन पैरामीटर के रूप में पारित करने की आवश्यकता है - यह बहुत कम घुसपैठ कर रहा था)।
टीएलडीआर: क्या उद्धृत पैरामीटर के भीतर विशेष वर्णों का सम्मान करने के लिए eval प्राप्त करने का कोई तरीका है, उन्हें बचने के बिना?
यदि आप बैश विशिष्ट संरचनाओं का उपयोग कर रहे हैं, तो आपकी लॉगिंग स्क्रिप्ट को "log.sh" नहीं कहा जाना चाहिए। यह "log.bash" होना चाहिए। –
@ विलियम पर्सेल - मैंने कुछ खोज की और शैल स्क्रिप्ट के नामकरण सम्मेलनों के संबंध में किसी भी प्रकार का मानक नहीं मिला। वास्तव में, ज्यादातर लोग पूरी तरह से एक प्रत्यय छोड़ने लगते हैं। ईमानदार होने के लिए मैंने कभी भी '\ *। Sh' (या, कोई विस्तार/प्रत्यय वाला स्क्रिप्ट) के अलावा कुछ भी नहीं देखा है। और सभी व्यावहारिकता में, इसका कोई प्रभाव नहीं होना चाहिए, है ना? दुभाषिया या तो स्क्रिप्ट की पहली पंक्ति से खींचा जाता है या आपका वर्तमान खोल उपयोग किया जाता है। ऐसा लगता है कि यह अनिवार्य रूप से व्यक्तिगत वरीयता के लिए नीचे आता है। लेकिन, शायद "\ *। Sh" किसी उपयोगकर्ता को इंगित कर सकता है कि स्क्रिप्ट "sh।" का उपयोग करती है – LousyG
एकमात्र व्यावहारिक प्रभाव तब होगा जब कोई डेवलपर आपके कार्यों का एक अलग खोल के साथ उपयोग कर रहा हो। '* .sh' नाम के साथ, एक डेवलपर उचित रूप से मान लेगा कि आपकी लाइब्रेरी को zsh स्क्रिप्ट में सोर्स किया जा सकता है। –