कमांड लाइन के तर्कों में किन वर्णों के भाग जाने की आवश्यकता है?


15

बैश में, जब कमांड लाइन तर्क को एक कमांड में निर्दिष्ट करता है, तो किन वर्णों को बचाना आवश्यक है?

वे बैश के अक्षरों से परे तक सीमित हैं: अंतरिक्ष, टैब, |, &, ;, (, ), <, और >?


मत भूलना (संभव) फ़ाइल नाम * के साथ ग्लोबिंग और?
जेफ स्कालर

धन्यवाद। आप पूरी तरह से उन पात्रों के प्रकारों को सूचीबद्ध कर सकते हैं जिन्हें सीएमडी लाइन आर्ग्स में बच निकलने की आवश्यकता है?
टिम

सूची का होना अच्छा है, लेकिन उद्धरण के बारे में समझने के लिए सबसे महत्वपूर्ण बात यह है: एकल उद्धरणों के बीच सब कुछ शाब्दिक और शब्द विभाजन के बिना पारित हो जाता है। कोई अपवाद नहीं। (इसका मतलब यह है कि किसी भी तरीके को एकल उद्धरणों के भीतर एम्बेड करने का कोई तरीका नहीं है, वैसे, लेकिन यह चारों ओर काम करना आसान है ।)
वाइल्डकार्ड

जवाबों:


22

निम्नलिखित वर्णों का शेल के कुछ संदर्भों में विशेष अर्थ है और उन्हें तर्कों में बच निकलने की आवश्यकता हो सकती है:

उन पात्रों में से कुछ का उपयोग अधिक चीजों के लिए किया जाता है और एक से अधिक स्थानों पर जो मैंने जोड़ा है।


कुछ कोने मामले हैं जो स्पष्ट रूप से वैकल्पिक हैं:

  • !के साथ अक्षम किया जा सकता है set +H, जो गैर-संवादात्मक गोले में डिफ़ॉल्ट है।
  • {के साथ अक्षम किया जा सकता है set +B
  • *और के ?साथ अक्षम किया जा सकता है set -fयाset -o noglob
  • =समान चिह्न (U + 003D) भी सक्षम होने set -kयाset -o keyword बच जाने की आवश्यकता है ।

एक नई पंक्ति से बचने के लिए उद्धरण की आवश्यकता होती है - बैकस्लैश काम नहीं करेगा। IFS में सूचीबद्ध किसी भी अन्य वर्ण को समान हैंडलिंग की आवश्यकता होगी। आप से बचने के लिए की जरूरत नहीं है ]या }है, लेकिन आप करते हैं से बचने के लिए की जरूरत है ), क्योंकि यह एक ऑपरेटर है।

इन पात्रों में से कुछ के लिए सख्त सीमाएं हैं जब उन्हें वास्तव में दूसरों की तुलना में भागने की आवश्यकता होती है। उदाहरण के लिए, a#bठीक है, लेकिन a #bएक टिप्पणी है, जबकि >दोनों संदर्भों में भागने की आवश्यकता होगी। यह उन सभी को रूढ़िवादी रूप से वैसे भी बचने के लिए चोट नहीं करता है, और यह ठीक भेदों को याद करने से आसान है।

अपने आदेश का नाम ही किसी खोल कीवर्ड है ( if, for, do) तो आप बच या यह बहुत उद्धृत करने के लिए की आवश्यकता होगी। उनमें से केवल एक दिलचस्प है in, क्योंकि यह स्पष्ट नहीं है कि यह हमेशा एक कीवर्ड है। आपको तर्क में उपयोग किए जाने वाले कीवर्ड के लिए ऐसा करने की आवश्यकता नहीं है, केवल तब जब आप (मूर्खतापूर्ण!) ने उनमें से एक के बाद एक कमांड का नाम दिया हो। शेल ऑपरेटर ( (और &, आदि) को हमेशा जहाँ कहीं भी उद्धृत करने की आवश्यकता होती है।


1 स्टीफन ने नोट किया है कि आपके स्थान से किसी अन्य एकल-बाइट रिक्त चरित्र को भी भागने की आवश्यकता है। अधिकांश सामान्य, समझदार स्थानों में, कम से कम C या UTF-8 के आधार पर, यह केवल ऊपर दिए गए व्हाट्सएप वर्ण हैं। कुछ ISO-8859-1 स्थानों में, U + 00A0 नो-ब्रेक स्पेस को रिक्त माना जाता है, जिसमें Solaris, BSDs और OS X (मुझे गलत लगता है) शामिल हैं। यदि आप एक अनजान लोकेल के साथ काम कर रहे हैं, तो यह सिर्फ अक्षरों के बारे में कुछ भी शामिल कर सकता है, इसलिए शुभकामनाएं।

वैचारिक रूप से, एक एकल बाइट माना जाने वाला रिक्त एक बहु-बाइट चरित्र के भीतर दिखाई दे सकता है , जो रिक्त नहीं था, और आपके पास उद्धरणों में पूरी बात डालने के अलावा उस से बचने का कोई रास्ता नहीं होगा। यह एक सैद्धांतिक चिंता का विषय नहीं है: ऊपर से एक ISO-8859-1 लोकेल में, जो A0बाइट को एक रिक्त माना जाता है वह UTF-8 एन्कोडेड "à" ( ) जैसे मल्टीबाइट वर्णों के भीतर दिखाई दे सकता है C3 A0। उन पात्रों को सुरक्षित रूप से संभालने के लिए आपको उन्हें उद्धृत करना होगा "à"। यह व्यवहार स्क्रिप्ट चलाने वाले वातावरण में स्थानीय कॉन्फ़िगरेशन पर निर्भर करता है, न कि उस जगह पर जहां आपने इसे लिखा था।

मुझे लगता है कि यह व्यवहार कई तरीकों से टूटा हुआ है, लेकिन हमें उस हाथ को खेलना होगा जिसे हम निपटा रहे हैं। यदि आप किसी भी गैर-स्व-सिंक्रनाइज़िंग मल्टीबीट कैरेक्टर सेट के साथ काम कर रहे हैं, तो सबसे सुरक्षित चीज सब कुछ बोली जाएगी। यदि आप UTF-8 या C में हैं, तो आप सुरक्षित हैं (फिलहाल)।


आपके स्थान में अन्य रिक्त स्थान (साथ ही मल्टी-बाइट एक बग के कारण ) को छोड़कर भागने की आवश्यकता होगी
स्टीफन चेज़लस

!जब केवल csh इतिहास विस्तार सक्षम किया जाता है, तो आपको बच निकलने की आवश्यकता होती है, आमतौर पर स्क्रिप्ट में नहीं। [ ! -f a ]या find . ! -name...ठीक हैं यह आपके तंग सीमा अनुभाग द्वारा कवर किया गया है लेकिन शायद स्पष्ट रूप से ध्यान देने योग्य है।
स्टीफन चेजलस

वहाँ संदर्भों जहां अन्य पात्रों की तरह के हवाले करने की जरूरत नहीं है ध्यान दें कि: hash[foo"]"]=, ${var-foo"}"}, [[ "!" = b ]], [[ a = "]]" ]], के लिए regexp ऑपरेटरों [[ x =~ ".+[" ]]। के अलावा कीवर्ड {( if, while, for...) उद्धृत किया ताकि वे इस तरह के रूप में मान्यता प्राप्त नहीं कर रहे हैं की आवश्यकता होगी ...
स्टीफन Chazelas

इस हद तक कि वे कमांड-लाइन तर्क हैं, व्याख्या विचाराधीन कमांड तक है (बस की तरह ]), इसलिए मैं उन्हें सूचीबद्ध कर रहा हूं। मुझे नहीं लगता कि किसी भी कीवर्ड को तर्क स्थिति में उद्धृत करने की आवश्यकता है।
माइकल होमर

2
बिल्डिंग्स, डैश, या% का उद्धरण कुछ भी नहीं करता है।
माइकल होमर

3

जीएनयू समानांतर में इसका परीक्षण किया जाता है और इसका बड़े पैमाने पर उपयोग किया जाता है:

$a =~ s/[\002-\011\013-\032\\\#\?\`\(\)\{\}\[\]\^\*\<\=\>\~\|\; \"\!\$\&\'\202-\377]/\\$&/go;
# quote newline as '\n'                                                                                                         
$a =~ s/[\n]/'\n'/go;

यह में परीक्षण किया जाता है bash, dash, ash, ksh, zsh, और fish। कुछ पात्रों को गोले के कुछ (संस्करणों) में उद्धृत करने की आवश्यकता नहीं है, लेकिन उपरोक्त सभी परीक्षण किए गए गोले में काम करता है।

यदि आप बस एक स्ट्रिंग उद्धृत करना चाहते हैं, तो आप इसे में पाइप कर सकते हैं parallel --shellquote:

printf "&*\t*!" | parallel --shellquote

मैंने पहले कैसे समानांतर के बारे में नहीं सुना है ...
टॉम एच

@ तोम की सराहना की जाएगी यदि आप 5 मिनट यह सोचकर खर्च कर सकते हैं कि हम आप तक कैसे पहुंच सकते हैं।
ओले तांगे

मुझे लगता है कि यह एक प्रगति समस्या है। जब तक वे कुछ जटिलता चरणों के माध्यम से आगे नहीं बढ़े हैं, ज्यादातर लोगों को समानांतर की आवश्यकता या समझ नहीं होती है। जिस समय तक वे xargs, nohup और उस तरह के सामान में आ गए। इसके अलावा, मैं कई लोगों को स्टैक एक्सचेंज में समस्याओं के समाधान के लिए समानांतर का उपयोग करते हुए नहीं देखता हूं या जब मैं समस्याओं को हल करने के लिए गूगल करता हूं
टॉम एच

1

पर्ल में हल्के भागने के समाधान के लिए, मैं एकल उद्धरण के सिद्धांत का पालन कर रहा हूं। सिंगल कोट्स में बैश-स्ट्रिंग में कोई भी कैरेक्टर हो सकता है, सिवाय सिंगल कोट के।

मेरा कोड:

my $bash_reserved_characters_re = qr([ !"#$&'()*;<>?\[\\`{|~\t\n]);

while(<>) {
    if (/$bash_reserved_characters_re/) {
        my $quoted = s/'/'"'"'/gr;
        print "'$quoted'";
    } else {
        print $_;
    }
}

उदाहरण रन 1:

$ echo -n "abc" | perl escape_bash_special_chars.pl
abc

उदाहरण रन 2:

echo "abc" | perl escape_bash_special_chars.pl
'abc
'

उदाहरण रन 3:

echo -n 'ab^c' | perl escape_bash_special_chars.pl
ab^c

उदाहरण रन 4:

echo -n 'ab~c' | perl escape_bash_special_chars.pl
'ab~c'

उदाहरण रन 5:

echo -n "ab'c" | perl escape_bash_special_chars.pl
'ab'"'"'c'

echo 'ab'"'"'c'
ab'c

हाँ, मान्य बिंदु है कि। मेरा विचार है कि अधिकांश लोग इस पृष्ठ पर उतरेंगे, क्योंकि उन्हें हल करने के लिए एक समस्या है। इसलिए नहीं कि यह एक दिलचस्प अकादमिक बहस है। इसीलिए मैं समाधान प्रदान करना चाहता हूँ और उनमें से गुणों पर चर्चा करना चाहता हूँ, जबकि थोड़ा-सा विषय भी।
जरी तुर्किया

मेरा कोड माइकल होमर के उत्तर का कार्यान्वयन है। मैंने जो भी किया उससे अधिक जानकारी लाने का इरादा नहीं था।
जरी तुर्किया
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.