किसी अन्य स्क्रिप्ट की सामग्री के रूप में उपयोग के लिए एक चर से बच


20

यह सवाल है नहीं कैसे एक सही तरीके से छोड़े स्ट्रिंग शाब्दिक लिखने के बारे में। मुझे कोई भी संबंधित प्रश्न नहीं मिल रहा है कि स्क्रिप्ट के भीतर या अन्य कार्यक्रमों द्वारा प्रत्यक्ष उपभोग के लिए चर से कैसे बचा जाए।

मेरा लक्ष्य एक स्क्रिप्ट को अन्य स्क्रिप्ट बनाने के लिए सक्षम करना है। ऐसा इसलिए है क्योंकि उत्पन्न स्क्रिप्ट में कार्य किसी अन्य मशीन पर 0 से n गुना तक कहीं भी चलेगा , और जिस डेटा से वे उत्पन्न हुए हैं, वे चलने से पहले बदल सकते हैं (फिर से), इसलिए ऑपरेशन सीधे कर रहे हैं, एक नेटवर्क पर काम नहीं।

एक ज्ञात चर को देखते हुए जिसमें विशेष वर्ण हो सकते हैं जैसे कि एकल उद्धरण, मुझे यह लिखना होगा कि पूरी तरह से बच गए स्ट्रिंग शाब्दिक के रूप में, उदाहरण के लिए एक चर fooयुक्त bar'bazस्क्रिप्ट उत्पन्न स्क्रिप्ट में दिखाई देनी चाहिए:

qux='bar'\''baz'

जो "qux=$foo_esc"स्क्रिप्ट की अन्य लाइनों के साथ जोड़कर लिखा जाएगा । मैंने इसे पर्ल का उपयोग करके इस तरह किया:

foo_esc="'`perl -pe 's/('\'')/\\1\\\\\\1\\1/g' <<<"$foo"`'"

लेकिन यह ओवरकिल की तरह लगता है।

मुझे केवल बैश के साथ इसे करने में कोई सफलता नहीं मिली है। मैंने इनमें से कई रूपों की कोशिश की है:

foo_esc="'${file//\'/\'\\\'\'}'"
foo_esc="'${file//\'/'\\''}'"

लेकिन या तो अतिरिक्त स्लैश आउटपुट में दिखाई देते हैं (जब मैं करता हूं echo "$foo"), या वे एक सिंटैक्स त्रुटि का कारण बनता है (शेल से किया गया है तो आगे इनपुट की उम्मीद करना)।


aliasऔर / या setकाफी सार्वभौमिक रूप से
mikeserv

@ mikeserv क्षमा करें, मुझे यकीन नहीं है कि आपका क्या मतलब है।
वॉल्फ

alias "varname=$varname" varnameयाvar=value set
mikeserv

2
@mikeserv मेरे लिए यह समझने के लिए पर्याप्त संदर्भ नहीं है कि आपका सुझाव क्या करना है, और न ही मैं इसे किसी भी चर से बचने के सामान्य तरीके के रूप में कैसे उपयोग करूंगा। यह एक सुलझी हुई समस्या है, दोस्त।
5

जवाबों:


27

बैश वास्तव में इस मामले के लिए एक पैरामीटर विस्तार विकल्प है :

${parameter@Q}विस्तार एक स्ट्रिंग है जो एक प्रारूप में उद्धृत पैरामीटर का मूल्य है जिसे इनपुट के रूप में पुन: उपयोग किया जा सकता है।

तो इस मामले में:

foo_esc="${foo@Q}"

यह बैश 4.4 और अप में समर्थित है। विस्तार के अन्य रूपों के लिए भी कई विकल्प हैं, और विशेष रूप से पूर्ण असाइनमेंट स्टेटमेंट ( @A) उत्पन्न करने के लिए ।


7
नीट, लेकिन केवल 4.2 है जो देता है bad substitution
वाल्फ

3
Z शैल समतुल्य है "${foo:q}"
JdeBP

सच में मेरी जान बचाओ! "${foo@Q}"काम करता है!
हाओ

@JdeBP कि Z शेल समतुल्य नहीं है। Zsh के लिए कोई अन्य विचार?
स्टीवन शो

1
मुझे जवाब मिला: "$ {(@ qq) foo}"
स्टीवन शॉ

11

बैश प्रारूप विनिर्देशक के printfसाथ एक बिलिन प्रदान करता है %q, जो आपके लिए शेल एस्केपिंग करता है, यहां तक ​​कि बैश के पुराने (<4.0) संस्करणों में भी।

printf '[%q]\n' "Ne'er do well"
# Prints [Ne\'er\ do\ well]

printf '[%q]\n' 'Sneaky injection $( whoami ) `ls /root`'
# Prints [Sneaky\ injection\ \$\(\ whoami\ \)\ \`ls\ /root\`]

इस ट्रिक का उपयोग किसी फ़ंक्शन से डेटा के सरणियों को वापस करने के लिए भी किया जा सकता है:

function getData()
{
  printf '%q ' "He'll say hi" 'or `whoami`' 'and then $( byebye )'
}

declare -a DATA="( $( getData ) )"
printf 'DATA: [%q]\n' "${DATA[@]}"
# Prints:
# DATA: [He\'ll\ say\ hi]
# DATA: [or\ \`whoami\`]
# DATA: [and\ then\ \$\(\ byebye\ \)]

ध्यान दें कि बैश printfबिल्टिन printfयूटिलिटी से अलग है जो ज्यादातर यूनिक्स जैसे ऑपरेटिंग सिस्टम के साथ आता है। यदि, किसी कारण से, printfकमांड बिल्टिन के बजाय उपयोगिता को आमंत्रित करता है, तो आप हमेशा builtin printfइसके बजाय निष्पादित कर सकते हैं ।


मुझे यकीन नहीं है कि यह कैसे मदद करता है अगर मुझे प्रिंट की आवश्यकता होगी 'Ne'\''er do well', आदि, अर्थात आउटपुट में शामिल उद्धरण।
वाल्फ

1
@ मुझे लगता है कि आप समझ नहीं रहे हैं कि दो रूप समतुल्य हैं, और दोनों एक दूसरे की तरह ही सुरक्षित हैं। जैसे [[ 'Ne'\''er do well' == Ne\'er\ do\ well ]] && echo 'equivalent!'गूंज equivalent!
उठेगी

मुझे यह याद आया: पी हालांकि मैं उद्धृत रूप को पसंद करता हूं क्योंकि यह सिंटैक्स-हाइलाइटिंग दर्शक / संपादक में पढ़ना आसान है।
वाल्फ जूल

@Walf ऐसा लगता है कि आपका दृष्टिकोण बहुत खतरनाक है, यह देखते हुए कि आपके उदाहरण में पर्ल, 'hello'गलत मान में परिणाम जैसे मूल्य दे रहा है ''\''hello'', जिसमें एक अनावश्यक अग्रणी खाली स्ट्रिंग (पहले दो एकल उद्धरण), और एक अनुचित अनुगामी एकल उद्धरण है।
देजय क्लेटन

1
@Walf, स्पष्टीकरण के लिए, बैश $'escape-these-chars'की ANSI-C उद्धरण विशेषता है जो निर्दिष्ट स्ट्रिंग के भीतर सभी वर्णों को बचाए जाने का कारण बनता है। इस प्रकार, आसानी से एक स्ट्रिंग शाब्दिक बनाने के लिए जिसमें फ़ाइल नाम के भीतर एक नई $'first-line\nsecond-line')\n
पंक्ति

8

मुझे लगता है कि मैं RTFM नहीं था। इसे ऐसे किया जा सकता है:

q_mid=\'\\\'\'
foo_esc="'${foo//\'/$q_mid}'"

फिर echo "$foo_esc"उम्मीद देता है'bar'\''baz'


मैं वास्तव में इसका उपयोग कैसे कर रहा हूँ यह एक फ़ंक्शन के साथ है:

function esc_var {
    local mid_q=\'\\\'\'
    printf '%s' "'${1//\'/$mid_q}'"
}

...

foo_esc="`esc_var "$foo"`"

इसे printfDejay के समाधान से अंतर्निहित उपयोग करने के लिए संशोधित करना :

function esc_vars {
    printf '%q' "$@"
}

3
अगर मेरे संस्करण ने इसका समर्थन किया तो मैं @ माइकल-होमर के समाधान का उपयोग करूंगा।
वॉल्फ

4

एक var मान को कोट करने के लिए कई समाधान हैं:

  1. उर्फ
    अधिकांश गोले में (जहाँ उर्फ ​​उपलब्ध है) (csh, tcsh और शायद अन्य जैसे csh को छोड़कर):

    $ alias qux=bar\'baz
    $ alias qux
    qux='bar'\''baz'

    हां, यह shडैश या राख जैसे कई प्रकार के गोले में काम करता है ।


  2. अधिकांश गोले में भी सेट करें (फिर से, csh नहीं):

    $ qux=bar\'baz
    $ set | grep '^qux='
    qux='bar'\''baz'
  3. टाइपसेट
    कुछ गोले में (ksh, bash और zsh कम से कम):

    $ qux=bar\'baz
    $ typeset -p qux
    typeset qux='bar'\''baz'             # this is zsh, quoting style may
                                         # be different for other shells.
  4. निर्यात
    पहले करें:

    export qux=bar\'baz

    फिर उपयोग करें:
    export -p | grep 'qux=' export -p | grep 'qux='
    export -p qux

  5. उद्धरण
    echo "${qux@Q}"
    echo "${(qq)qux}" # एक से चार q का उपयोग किया जा सकता है।


उपनाम दृष्टिकोण चतुर है और ऐसा लगता है कि यह POSIX द्वारा निर्दिष्ट किया गया है। अधिकतम पोर्टेबिलिटी के लिए मुझे लगता है कि यह जाने का तरीका है। मेरा मानना ​​है कि एम्बेडेड न्यूलाइन्स वाले वेरिएबल्स के grepसाथ जुड़े सुझाव टूट सकते हैं exportया setहो सकते हैं।
jw013
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.