बैश में, जब कमांड लाइन तर्क को एक कमांड में निर्दिष्ट करता है, तो किन वर्णों को बचाना आवश्यक है?
वे बैश के अक्षरों से परे तक सीमित हैं: अंतरिक्ष, टैब,
|
, &
, ;
, (
, )
, <
, और >
?
बैश में, जब कमांड लाइन तर्क को एक कमांड में निर्दिष्ट करता है, तो किन वर्णों को बचाना आवश्यक है?
वे बैश के अक्षरों से परे तक सीमित हैं: अंतरिक्ष, टैब,
|
, &
, ;
, (
, )
, <
, और >
?
जवाबों:
निम्नलिखित वर्णों का शेल के कुछ संदर्भों में विशेष अर्थ है और उन्हें तर्कों में बच निकलने की आवश्यकता हो सकती है:
`
बैकटिक (U + 0060 ग्रेव एक्सेंट)~
टिल्ड (U + 007E)!
विस्मयादिबोधक चिह्न (U + 0021)#
हैश (U + 0023 नंबर साइन)$
डॉलर चिन्ह (U + 0024)&
एम्परसैंड (U + 0026)*
तारांकन चिह्न (U + 002A)(
बाएं कोष्ठक (U + 0028))
सही कोष्ठक (U + 0029)
( ⇥
) टैब (U + 0009){
लेफ्ट ब्रेस (U + 007B लेफ्ट कर्ली ब्रैकेट)[
बाएं वर्ग कोष्ठक (U + 005B)|
वर्टिकल बार (U + 007C वर्टिकल लाइन)\
बैकलैश (U + 005C रिवर्स सॉलिडस);
अर्धविराम (U + 003B)'
एकल उद्धरण / एपोस्ट्रोफ (U + 0027)"
दोहरी बोली (U + 0022)↩
नई लाइन (U + 000A)<
से कम (U + 003C)>
से अधिक (U + 003E)?
प्रश्न चिह्न (U + 003F)
अंतरिक्ष (U + 0020) 1उन पात्रों में से कुछ का उपयोग अधिक चीजों के लिए किया जाता है और एक से अधिक स्थानों पर जो मैंने जोड़ा है।
कुछ कोने मामले हैं जो स्पष्ट रूप से वैकल्पिक हैं:
!
के साथ अक्षम किया जा सकता है 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
...) उद्धृत किया ताकि वे इस तरह के रूप में मान्यता प्राप्त नहीं कर रहे हैं की आवश्यकता होगी ...
]
), इसलिए मैं उन्हें सूचीबद्ध कर रहा हूं। मुझे नहीं लगता कि किसी भी कीवर्ड को तर्क स्थिति में उद्धृत करने की आवश्यकता है।
जीएनयू समानांतर में इसका परीक्षण किया जाता है और इसका बड़े पैमाने पर उपयोग किया जाता है:
$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
पर्ल में हल्के भागने के समाधान के लिए, मैं एकल उद्धरण के सिद्धांत का पालन कर रहा हूं। सिंगल कोट्स में बैश-स्ट्रिंग में कोई भी कैरेक्टर हो सकता है, सिवाय सिंगल कोट के।
मेरा कोड:
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