सिंगल कोटेड स्ट्रिंग्स के भीतर सिंगल कोट्स से कैसे बचें


1015

मान लीजिए, आपके पास बैश है aliasजैसे:

alias rxvt='urxvt'

जो ठीक काम करता है

तथापि:

alias rxvt='urxvt -fg '#111111' -bg '#111111''

काम नहीं करेगा, और न ही होगा:

alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''

एक बार जब आप उद्धरण छोड़ देते हैं तो आप स्ट्रिंग के अंदर खुलने और बंद होने वाले उद्धरणों का मिलान कैसे करते हैं?

alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''

हालांकि यह उसी तरह का प्रतिनिधित्व करेगा, अगर आप उन्हें इस तरह से अवगत कराने की अनुमति देते हैं, तो दुर्भाग्यपूर्ण लगता है।


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


3
नेस्टेड डबल कोट्स पलायन योग्य हैं "\"", इसलिए जब भी संभव हो @ लियोरी के जवाब के लिए उन्हें प्राथमिकता में इस्तेमाल किया जाना चाहिए।
एलन

7
डबल उद्धरण * निक्स (बैश सहित और संबंधित उपकरण जैसे पर्ल) से एकल उद्धरणों से काफी अलग व्यवहार करते हैं, इसलिए जब भी एकल उद्धरणों के साथ कोई समस्या नहीं होती है, तो दोहरे उद्धरणों को प्रतिस्थापित करना एक अच्छा समाधान नहीं है। दोहरे उद्धरण $ निर्दिष्ट करते हैं ... चर को निष्पादन से पहले प्रतिस्थापित किया जाना है, जबकि एकल उद्धरण $ निर्दिष्ट करते हैं ... का शाब्दिक रूप से इलाज किया जाना है।
चक कोलारस

यदि आप सोच रहे हैं, तो मैंने दोहरे उद्धरण चिह्नों का उपयोग किया है लेकिन यह अभी भी काम नहीं कर रहा है , फिर से आपकी स्क्रिप्ट का स्रोत।
सैमी बेनचेरीफ

जवाबों:


1453

यदि आप वास्तव में सबसे बाहरी परत में एकल उद्धरण का उपयोग करना चाहते हैं, तो याद रखें कि आप दोनों प्रकार के उद्धरण को गोंद कर सकते हैं। उदाहरण:

 alias rxvt='urxvt -fg '"'"'#111111'"'"' -bg '"'"'#111111'"'"
 #                     ^^^^^       ^^^^^     ^^^^^       ^^^^
 #                     12345       12345     12345       1234

'"'"'इसकी व्याख्या कैसे की जाती है ':

  1. ' पहला उद्धरण समाप्त करें जो एकल उद्धरण का उपयोग करता है।
  2. " दोहरे उद्धरण चिह्नों का उपयोग करके दूसरा उद्धरण शुरू करें।
  3. ' उद्धृत चरित्र।
  4. " दोहरे उद्धरण चिह्नों का उपयोग करके दूसरा उद्धरण समाप्त करें।
  5. ' एकल उद्धरण का उपयोग करके, तीसरा उद्धरण शुरू करें।

यदि आप (1) और (2), या (4) और (5) के बीच कोई व्हाट्सएप नहीं रखते हैं, तो शेल उस स्ट्रिंग को एक लंबे शब्द के रूप में व्याख्या करेगा।


5
alias splitpath='echo $PATH | awk -F : '"'"'{print "PATH is set to"} {for (i=1;i<=NF;i++) {print "["i"]",$i}}'"'"यह तब काम करता है जब उर्फ ​​स्ट्रिंग में एकल उद्धरण और दोहरे उद्धरण दोनों होते हैं!
उपिल_ क्या 1

17
मेरी व्याख्या: अलग-अलग उद्धृत स्ट्रिंग अभिव्यक्तियों को स्पष्ट रूप से संक्षिप्त करें।
बेंजामिन एटकिन

2
मेरे लिए काम किया, डबल बच गए सिंगल कोट्स का उदाहरण:alias serve_this_dir='ruby -rrack -e "include Rack;Handler::Thin.run Builder.new{run Directory.new'"'"''"'"'}"'
JAMESSTONEco

2
निश्चित रूप से सबसे पठनीय समाधान नहीं है। यह एकल उद्धरणों का उपयोग करता है जहां उन्हें वास्तव में जरूरत नहीं है।
oberlies

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

263

मैं हमेशा अनुक्रम के साथ प्रत्येक एम्बेडेड एकल उद्धरण को प्रतिस्थापित करता हूं: '\''(वह है: उद्धरण बैकस्लैश उद्धरण उद्धरण) जो स्ट्रिंग को बंद कर देता है, एक बची हुई एकल बोली को जोड़ देता है और स्ट्रिंग को फिर से खोल देता है।


मैं अक्सर मेरे लिए यह करने के लिए अपनी पर्ल स्क्रिप्ट्स में एक "quotify" फ़ंक्शन को कोड़ा मारता हूं। चरण होंगे:

s/'/'\\''/g    # Handle each embedded quote
$_ = qq['$_']; # Surround result with single quotes.

यह बहुत अधिक सभी मामलों का ख्याल रखता है।

जब आप evalअपने शेल-स्क्रिप्ट में परिचय करते हैं तो जीवन और अधिक मजेदार हो जाता है । आपको अनिवार्य रूप से फिर से सब कुछ फिर से उद्धृत करना होगा!

उदाहरण के लिए, ऊपर दिए गए कथनों से युक्त उद्धरण नामक एक पर्ल स्क्रिप्ट बनाएं:

#!/usr/bin/perl -pl
s/'/'\\''/g;
$_ = qq['$_'];

फिर इसका उपयोग सही ढंग से उद्धृत स्ट्रिंग उत्पन्न करने के लिए करें:

$ quotify
urxvt -fg '#111111' -bg '#111111'

परिणाम:

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

जो तब उपनाम / आदेश में कॉपी / पेस्ट किया जा सकता है:

alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

(यदि आपको कमांड को एक eval में सम्मिलित करने की आवश्यकता है, तो फिर से उद्धरण को चलाएँ:

 $ quotify
 alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

परिणाम:

'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''

जिसे कॉपी / पेस्ट किया जा सकता है:

eval 'alias rxvt='\''urxvt -fg '\''\'\'''\''#111111'\''\'\'''\'' -bg '\''\'\'''\''#111111'\''\'\'''\'''\'''

1
लेकिन यह बुरा नहीं है। और जैसा कि स्टीव बी ने ऊपर उल्लेख किया है, "गन्नू संदर्भ मैनुअल" के अपने संदर्भ के साथ, आप एक ही प्रकार के उद्धरण में उद्धरण से बच नहीं सकते हैं। और वास्तव में, उन्हें वैकल्पिक उद्धरणों के भीतर भागने की ज़रूरत नहीं है, उदाहरण के लिए "" "एक वैध एकल-उद्धरण स्ट्रिंग है और '"' किसी भी भागने की आवश्यकता के बिना एक वैध डबल-उद्धरण स्ट्रिंग है।
nicerobot

8
@nicerobot: मैंने एक उदाहरण दिखाते हुए कहा है कि: 1) मैं एक ही प्रकार के उद्धरणों के भीतर उद्धरणों से बचने का प्रयास नहीं करता, 2) और न ही वैकल्पिक उद्धरणों में, और 3) पर्ल का उपयोग वैध बनाने की प्रक्रिया को स्वचालित करने के लिए किया जाता है bash string containg imbedded quotes
एड्रियन प्रैंक

18
अपने आप में पहला पैराग्राफ वह उत्तर है जिसकी मुझे तलाश थी।
डेव कॉसे

9
यह वही पार्टी के साथ-साथ, टाइप करता है set -xऔर echo "here's a string"और आप उस पार्टी कार्यान्वित देखेंगे echo 'here'\''s a string'। ( set +xसामान्य व्यवहार लौटाने के लिए)
arekolek

195

चूंकि बैश 2.04 सिंटैक्स $'string'(केवल के बजाय 'string'; चेतावनी: के साथ भ्रमित न करें $('string')) एक और उद्धृत तंत्र है जो एएनएसआई सी जैसे भागने अनुक्रमों की अनुमति देता है और एकल-उद्धृत संस्करण तक विस्तार करता है।

सरल उदाहरण:

  $> echo $'aa\'bb'
  aa'bb

  $> alias myvar=$'aa\'bb'
  $> alias myvar
  alias myvar='aa'\''bb'

आपके मामले में:

$> alias rxvt=$'urxvt -fg \'#111111\' -bg \'#111111\''
$> alias rxvt
alias rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

सामान्य बचने के क्रम उम्मीद के मुताबिक काम करते हैं:

\'     single quote
\"     double quote
\\     backslash
\n     new line
\t     horizontal tab
\r     carriage return

नीचे से man bash( + 4.4 संस्करण) संबंधित दस्तावेज़ को कॉपी किया गया है :

$ 'स्ट्रिंग' रूप के शब्द विशेष रूप से व्यवहार किए जाते हैं। यह शब्द ANSI C मानक द्वारा निर्दिष्ट बैकस्लैश-एस्कैप्ड वर्णों के साथ स्ट्रिंग में फैलता है। बैकस्लैश एस्केप सीक्वेंस, यदि मौजूद हैं, तो निम्नानुसार डिकोड किए जाते हैं:

    \a     alert (bell)
    \b     backspace
    \e
    \E     an escape character
    \f     form feed
    \n     new line
    \r     carriage return
    \t     horizontal tab
    \v     vertical tab
    \\     backslash
    \'     single quote
    \"     double quote
    \?     question mark
    \nnn   the eight-bit character whose value is the octal 
           value nnn (one to three digits)
    \xHH   the eight-bit character whose value is the hexadecimal
           value HH (one or two hex digits)
    \uHHHH the Unicode (ISO/IEC 10646) character whose value is 
           the hexadecimal value HHHH (one to four hex digits)
    \UHHHHHHHH the Unicode (ISO/IEC 10646) character whose value 
               is the hexadecimal value HHHHHHHH (one to eight 
               hex digits)
    \cx    a control-x character

विस्तारित परिणाम एकल-उद्धृत है, जैसे कि डॉलर का चिह्न मौजूद नहीं था।


उद्धरण और पलायन देखें : अधिक विवरण के लिए bash-hackers.org wiki पर तार की तरह ANSI C। यह भी ध्यान दें कि "बैश चेंजेस" फ़ाइल ( यहाँ अवलोकन ) में परिवर्तन और बग फिक्सिंग के लिए बहुत कुछ उल्लेख किया गया $'string'है।

Unix.stackexchange.com के अनुसार एक सामान्य के रूप में एक विशेष चरित्र का उपयोग कैसे करें? यह काम (कुछ विविधताओं के साथ) को bash, zsh, mksh, ksh93 और FreeBSD और busybox sh में करना चाहिए।


इस्तेमाल किया जा सकता है, लेकिन यहां उद्धृत एकल स्ट्रिंग एक वास्तविक एकल उद्धृत नहीं है, इस स्ट्रिंग की सामग्री को शेल द्वारा इंटरप्रिट किया जा सकता है: echo $'foo\'b!ar'=> !ar': event not found
regilero 28'14

2
मेरी मशीन पर > echo $BASH_VERSION 4.2.47(1)-release > echo $'foo\'b!ar' foo'b!ar
mj41

1
हां, यह "हो सकता है" का कारण है, मेरे पास यह लाल टोपी 6.4 पर था, निश्चित रूप से एक पुराना बैश संस्करण।
Regilero

बैश चेंजलॉग में बहुत सारे बग फिक्स हैं, जो $'शायद सबसे आसान तरीका है, इसे पुराने सिस्टम पर खुद आजमाएं।
mj41

जागरूक रहें : tiswww.case.edu/php/chet/bash/CHANGESe. Bash no longer inhibits C-style escape processing ($'...') while performing pattern substitution word expansions. से लिया गया । अभी भी 4.3.42 में काम करता है लेकिन 4.3.48 में नहीं।
स्टिलर_लेसर

49

मुझे उनके ब्लॉग पर लिंक दिखाई नहीं दे रहा है (लिंक pls?), लेकिन ग्नू संदर्भ मैनुअल के अनुसार :

एकल उद्धरणों ('' '') में वर्णों को शामिल करना उद्धरणों के भीतर प्रत्येक वर्ण के शाब्दिक मूल्य को संरक्षित करता है। एकल उद्धरण के बीच एक एकल उद्धरण नहीं हो सकता है, तब भी जब एक बैकस्लैश द्वारा पूर्ववर्ती हो।

इतनी मार नहीं समझेगी:

alias x='y \'z '

हालाँकि, आप ऐसा कर सकते हैं यदि आप दोहरे उद्धरण चिह्नों से घिरे हों:

alias x="echo \'y "
> x
> 'y


दोहरे उद्धरण चिह्नों के साथ संलग्न सामग्री का मूल्यांकन किया जा रहा है, इसलिए दोहरे उद्धरण चिह्नों में केवल एक उद्धरण संलग्न करना उचित समाधान प्रतीत होता है।
पिओट्र डोब्रोगॉस्ट 17

3
यह प्रश्न का वास्तविक उत्तर है। हालांकि स्वीकृत जवाब एक समाधान प्रदान कर सकता है, यह तकनीकी रूप से एक सवाल का जवाब दे रहा है जो नहीं पूछा गया था।
मैथ्यू जी

3
मैथ्यू, सवाल एकल उद्धरण के अंदर एकल उद्धरण से बचने के बारे में था। यह उत्तर उपयोगकर्ता को अपना व्यवहार बदलने के लिए कहता है, और यदि आपके पास दोहरे उद्धरण चिह्नों का उपयोग करने में बाधा है (जैसा कि प्रश्न शीर्षक से पता चलता है), तो यह उत्तर मदद नहीं करेगा। हालांकि यह बहुत उपयोगी है (हालांकि स्पष्ट है), और इस तरह से एक उत्थान के हकदार हैं, लेकिन स्वीकार किए गए जवाब सटीक समस्या के बारे में पूछे जाने वाले पते को संबोधित करते हैं।
फर्नांडो कोर्डेइरो

दोहरे उद्धरण स्ट्रिंग में किसी एक उद्धरण को उद्धृत करने की आवश्यकता नहीं है।
मैथ्यू डी। शोलेफील्ड

32

मैं इस बात की पुष्टि कर सकता हूं कि '\''एक एकल-उद्धृत स्ट्रिंग के अंदर एक एकल उद्धरण के लिए उपयोग करना बैश में काम करता है, और इसे उसी तरह समझाया जा सकता है जैसे कि थ्रेड में पहले से "gluing" तर्क। मान लीजिए कि हमारे पास एक उद्धृत स्ट्रिंग है: 'A '\''B'\'' C'(यहां सभी उद्धरण एकल उद्धरण हैं)। यदि इसे प्रतिध्वनित किया जाता है, तो यह निम्नलिखित प्रिंट करता है A 'B' C:। प्रत्येक '\''पहले उद्धरण में मौजूदा एकल-उद्धृत स्ट्रिंग को बंद कर दिया जाता है, निम्नलिखित \'glues पिछले स्ट्रिंग के लिए एक एकल उद्धरण ( \'एक उद्धृत स्ट्रिंग शुरू किए बिना एक एकल उद्धरण निर्दिष्ट करने का एक तरीका है), और अंतिम उद्धरण एक और एकल-स्ट्रिंग को खोलता है।


2
यह भ्रामक है, यह वाक्य रचना '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' नहीं एक '' '' '' '' '' '' '' '' '' '' रूपी '' '' '' 'सिंटैक्स' '' '' '' '' '' '' '' '' '' '' 'भाग' '' '' के रूप में है। इस कथन 'ए' '' बी '' बी '' सी '' में आप 5 \
_

1
@teknopaul असाइनमेंट एक स्ट्रिंग होने के alias something='A '\''B'\'' C'परिणामस्वरूप होता है something, इसलिए भले ही असाइनमेंट के दाईं ओर तकनीकी रूप से एक स्ट्रिंग नहीं है, मुझे नहीं लगता कि यह बहुत मायने रखता है।
तेमू लीस्टी सेप

हालांकि यह आपके उदाहरण में काम करता है, यह तकनीकी रूप से एक समाधान प्रदान नहीं करता है कि किसी एकल उद्धरण स्ट्रिंग के अंदर एक उद्धरण कैसे डाला जाए। आप पहले ही इसे समझा चुके हैं, लेकिन हाँ यह कर रहा है 'A ' + ' + 'B' + ' + ' C'। दूसरे शब्दों में, एकल-उद्धृत स्ट्रिंग के अंदर एकल उद्धरण वर्णों को सम्मिलित करने का एक समाधान मुझे इस तरह का एक स्ट्रिंग बनाने की अनुमति देता है, और इसे प्रिंट करना चाहिए। हालाँकि यह समाधान इस मामले में काम नहीं करेगा। STR='\''; echo $STR। जैसा कि डिज़ाइन किया गया है, BASH वास्तव में इसकी अनुमति नहीं देता है।
krb686

@ मिखाइल_ बी, हां, '\''बैश के लिए काम करता है। क्या आप बता सकते हैं कि gnu.org/software/bash/manual/bashref.html में से कौन सा वर्ग इस तरह के व्यवहार को निर्दिष्ट करता है?
जिंगुओ याओ

20

दोनों संस्करण काम कर रहे हैं, या तो बच गए एकल उद्धरण चरित्र (\ ') का उपयोग करके, या दोहरे उद्धरणों ("" ") के भीतर एकल उद्धरण चरित्र को संलग्न करके सहमति के साथ।

प्रश्न के लेखक ने यह नहीं देखा कि उसके अंतिम भागने के प्रयास के अंत में एक अतिरिक्त एकल उद्धरण (') था:

alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
           │         │┊┊|       │┊┊│     │┊┊│       │┊┊│
           └─STRING──┘┊┊└─STRIN─┘┊┊└─STR─┘┊┊└─STRIN─┘┊┊│
                      ┊┊         ┊┊       ┊┊         ┊┊│
                      ┊┊         ┊┊       ┊┊         ┊┊│
                      └┴─────────┴┴───┰───┴┴─────────┴┘│
                          All escaped single quotes    │
                                                       │
                                                       ?

जैसा कि आप ASCII / यूनिकोड कला के पिछले अच्छे अंश में देख सकते हैं, अंतिम बची हुई एकल बोली (\ ') के बाद एक अनावश्यक एकल उद्धरण (') है। नोटपैड ++ में मौजूद सिंटेक्स-हाइलाइटर का उपयोग करना बहुत मददगार साबित हो सकता है।

निम्नलिखित की तरह एक और उदाहरण के लिए भी यही सच है:

alias rc='sed '"'"':a;N;$!ba;s/\n/, /g'"'"
alias rc='sed '\'':a;N;$!ba;s/\n/, /g'\'

एलियसेस के ये दो खूबसूरत उदाहरण बहुत ही जटिल और मोटे तौर पर दिखाते हैं कि किसी फ़ाइल को कैसे पंक्तिबद्ध किया जा सकता है। अर्थात्, बहुत सी पंक्तियों वाली फ़ाइल से आपको पिछली पंक्तियों की सामग्री के बीच अल्पविराम और रिक्त स्थान के साथ केवल एक पंक्ति मिलती है। पिछली टिप्पणी की समझ बनाने के लिए, निम्नलिखित एक उदाहरण है:

$ cat Little_Commas.TXT
201737194
201802699
201835214

$ rc Little_Commas.TXT
201737194, 201802699, 201835214

3
ASCII सारणी चित्रण के लिए उपार्जित :)
php-dev

16

शेल में उद्धरण से बचने का सरल उदाहरण:

$ echo 'abc'\''abc'
abc'abc
$ echo "abc"\""abc"
abc"abc

यह पहले से ही खोले 'गए एक ( \') को खत्म करने के द्वारा किया गया है , एक को छोड़कर ( ), फिर दूसरे को खोलकर ( ')। यह सिंटेक्स सभी कमांड्स के लिए काम करता है। यह 1 उत्तर के लिए बहुत समान है।


15

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

rxvt() { urxvt -fg "#${1:-000000}" -bg "#${2:-FFFFFF}"; }

जिसे तब आप कॉल कर सकते हैं:

rxvt 123456 654321

यह विचार कि आप अब उद्धरण के लिए चिंता के बिना इसे उर्फ ​​कर सकते हैं:

alias rxvt='rxvt 123456 654321'

या, यदि आपको #किसी कारण से सभी कॉल में शामिल करने की आवश्यकता है :

rxvt() { urxvt -fg "${1:-#000000}" -bg "${2:-#FFFFFF}"; }

जिसे तब आप कॉल कर सकते हैं:

rxvt '#123456' '#654321'

फिर, निश्चित रूप से, एक उपनाम है:

alias rxvt="rxvt '#123456' '#654321'"

(उफ़, मुझे लगता है कि मैं उद्धृत को संबोधित किया :)


1
मैं सिंगल कोट्स के भीतर कुछ करने की कोशिश कर रहा था जो डबल कोट्स में थे, जो कि सिंगल कोट्स में थे। ओह। "एक अलग दृष्टिकोण का प्रयास करें" के आपके उत्तर के लिए धन्यवाद। इससे फर्क पड़ा।
क्लिंटन ब्लैकमोर

1
मुझे 5 साल की देर हो चुकी है, लेकिन क्या आप अपने अंतिम उपनाम में एक भी उद्धरण याद नहीं कर रहे हैं?
जुलिएन

1
@ जुलिएन मैं एक समस्या नहीं देखता ;-)
nicerobot

11

चूँकि कोई एकल उद्धृत तारों के भीतर एकल उद्धरण नहीं डाल सकता, इसलिए सबसे सरल और सबसे पठनीय विकल्प एक हेरेडॉट स्ट्रिंग का उपयोग करना है

command=$(cat <<'COMMAND'
urxvt -fg '#111111' -bg '#111111'
COMMAND
)

alias rxvt=$command

ऊपर दिए गए कोड में, HEREDOC को catकमांड भेजा जाता है और उस का आउटपुट कमांड प्रतिस्थापन नोटेशन के माध्यम से एक चर को सौंपा जाता है$(..)

HEREDOC के चारों ओर एक ही उद्धरण डालना आवश्यक है क्योंकि यह एक के भीतर है $()


काश मैं इससे पहले बहुत दूर तक स्क्रॉल करता - मैं इस दृष्टिकोण को फिर से मजबूत करता और इसे पोस्ट करने के लिए यहां आता! यह अन्य सभी भागने के दृष्टिकोणों की तुलना में अधिक साफ और अधिक पठनीय है। ऐसा नहीं है कि यह कुछ गैर-बैश शेल पर काम नहीं करेगा, जैसे कि dashउबंटू अपस्टार्ट स्क्रिप्ट और अन्य जगहों पर डिफ़ॉल्ट शेल।
कोर्न

धन्यवाद! मैंने जो देखा, उसके लिए कमांड को परिभाषित करने का तरीका heredoc के माध्यम से है और ऑटो को कमांड से ssh में पास करें। BTW बिल्ली << उद्धरण के बिना कमान आदेश के अंदर vatiables प्रक्षेपित करने की अनुमति देता है और इस दृष्टिकोण के लिए भी काम करता है।
इगोर Tverdovskiy

10

मैं सिर्फ शेल कोड का उपयोग करता हूं .. जैसे \x27या \\x22लागू। कोई परेशानी नहीं, वास्तव में।


क्या आप ऑपरेशन में इसका एक उदाहरण दिखा सकते हैं? मेरे लिए यह सिर्फ एक शाब्दिक x27(सेंटोस 6.6 पर)
विल शेपर्ड

6

इनमें से अधिकांश उत्तर उस विशिष्ट मामले पर हिट करते हैं जिसके बारे में आप पूछ रहे हैं। वहाँ एक सामान्य दृष्टिकोण एक दोस्त है कि और मैं विकसित किया है कि मनमाने ढंग से मामले में के हवाले से आप की जरूरत के लिए अनुमति देता है के लिए बोली बैश आदेशों खोल विस्तार, जैसे की कई परतों, ssh के माध्यम से के माध्यम से, su -c, bash -c, आदि एक कोर आदिम आप की जरूरत है, यहाँ भी नहीं है देशी बाश में:

quote_args() {
    local sq="'"
    local dq='"'
    local space=""
    local arg
    for arg; do
        echo -n "$space'${arg//$sq/$sq$dq$sq$dq$sq}'"
        space=" "
    done
}

यह वास्तव में यही कहता है: यह प्रत्येक तर्क को व्यक्तिगत रूप से उद्धृत करता है (विस्तार के बाद, निश्चित रूप से):

$ quote_args foo bar
'foo' 'bar'
$ quote_args arg1 'arg2 arg2a' arg3
'arg1' 'arg2 arg2a' 'arg3'
$ quote_args dq'"'
'dq"'
$ quote_args dq'"' sq"'"
'dq"' 'sq'"'"''
$ quote_args "*"
'*'
$ quote_args /b*
'/bin' '/boot'

यह विस्तार की एक परत के लिए स्पष्ट काम करता है:

$ bash -c "$(quote_args echo a'"'b"'"c arg2)"
a"b'c arg2

(ध्यान दें कि $(quote_args ...)परिणाम को एक एकल तर्क में बनाने के लिए आसपास के दोहरे उद्धरण आवश्यक हैं bash -c।) और इसे विस्तार की कई परतों के माध्यम से ठीक से उद्धृत करने के लिए अधिक सामान्यतः उपयोग किया जा सकता है:

$ bash -c "$(quote_args bash -c "$(quote_args echo a'"'b"'"c arg2)")"
a"b'c arg2

उपरोक्त उदाहरण:

  1. शेल प्रत्येक उद्धरण को आंतरिक रूप से quote_argsव्यक्तिगत रूप से बताता है और फिर परिणामी आउटपुट को एक एकल तर्क में आंतरिक दोहरे उद्धरणों के साथ जोड़ता है।
  2. खोल-उद्धरण bash, -cऔर चरण 1 से पहले ही एक बार उद्धृत परिणाम है, और फिर बाहरी दोहरे उद्धरण चिह्नों के साथ एक एकल बहस में परिणाम को जोड़ती है।
  3. उस मेस को बाहरी के तर्क के रूप में भेजता है bash -c

संक्षेप में यह विचार है। आप इसके साथ कुछ बहुत जटिल चीजें कर सकते हैं, लेकिन आपको मूल्यांकन के क्रम के बारे में सावधान रहना होगा और इसके बारे में जो सब्स्टीट्यूशन उद्धृत किए गए हैं। उदाहरण के लिए, निम्नलिखित गलत काम करते हैं ("गलत" की कुछ परिभाषा के लिए):

$ (cd /tmp; bash -c "$(quote_args cd /; pwd 1>&2)")
/tmp
$ (cd /tmp; bash -c "$(quote_args cd /; [ -e *sbin ] && echo success 1>&2 || echo failure 1>&2)")
failure

पहले उदाहरण में, बैश तुरंत quote_args cd /; pwd 1>&2दो अलग-अलग कमांडों में फैलता है , quote_args cd /और pwd 1>&2, इसलिए /tmpजब pwdकमांड निष्पादित होता है, तो CWD अभी भी है। दूसरा उदाहरण ग्लोबिंग के लिए एक समान समस्या दिखाता है। दरअसल, सभी बैश विस्तार के साथ एक ही मूल समस्या होती है। यहां समस्या यह है कि एक कमांड प्रतिस्थापन एक फ़ंक्शन कॉल नहीं है: यह शाब्दिक रूप से एक बैश स्क्रिप्ट का मूल्यांकन कर रहा है और दूसरे आउटपुट स्क्रिप्ट के भाग के रूप में इसके आउटपुट का उपयोग कर रहा है।

यदि आप शेल संचालकों से बचने का प्रयास करते हैं, तो आप विफल हो जाएंगे क्योंकि परिणामी स्ट्रिंग को पारित कर दिया गया bash -cहै, जो कि व्यक्तिगत रूप से उद्धृत स्ट्रिंग्स का एक अनुक्रम है, जिसे तब ऑपरेटरों के रूप में व्याख्या नहीं किया जाता है, जो यह देखना आसान है कि क्या आप स्ट्रिंग को प्रतिध्वनित करते हैं? बैश करने के लिए पारित किया गया है:

$ (cd /tmp; echo "$(quote_args cd /\; pwd 1\>\&2)")
'cd' '/;' 'pwd' '1>&2'
$ (cd /tmp; echo "$(quote_args cd /\; \[ -e \*sbin \] \&\& echo success 1\>\&2 \|\| echo failure 1\>\&2)")
'cd' '/;' '[' '-e' '*sbin' ']' '&&' 'echo' 'success' '1>&2' '||' 'echo' 'failure' '1>&2'

यहाँ समस्या यह है कि आप अति-उद्धृत कर रहे हैं। परिचालकों के इनपुट के रूप में आपको जो कुछ भी आवश्यक है, वह ऑपरेटरों के लिए है bash -c, जिसका अर्थ है कि उन्हें $(quote_args ...)कमांड प्रतिस्थापन के बाहर होना चाहिए ।

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

$ (cd /tmp; echo "$(quote_args cd /); $(quote_args pwd) 1>&2")
'cd' '/'; 'pwd' 1>&2
$ (cd /tmp; bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")
/
$ (cd /tmp; echo "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")
'cd' '/'; [ -e *'sbin' ] && 'echo' 'success' 1>&2 || 'echo' 'failure' 1>&2
$ (cd /tmp; bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")
success

एक बार जब आप ऐसा कर लेते हैं, तो संपूर्ण स्ट्रिंग मूल्यांकन के मनमाने स्तरों को उद्धृत करने के लिए उचित खेल है:

$ bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")"
/
$ bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")")"
/
$ bash -c "$(quote_args bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); $(quote_args pwd) 1>&2")")")"
/
$ bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")"
success
$ bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *sbin ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")")"
success
$ bash -c "$(quote_args bash -c "$(quote_args bash -c "$(quote_args cd /tmp); $(quote_args bash -c "$(quote_args cd /); [ -e *$(quote_args sbin) ] && $(quote_args echo success) 1>&2 || $(quote_args echo failure) 1>&2")")")"
success

आदि।

इन उदाहरणों अतिव्य्घ्र दिया लग सकता है कि शब्द की तरह है success, sbinऔर pwdखोल उद्धृत करने की आवश्यकता नहीं है, लेकिन प्रमुख मुद्दा जब एक स्क्रिप्ट मनमाने ढंग से इनपुट लेने लेखन याद करने के लिए है कि आप सब कुछ आप पूरी तरह से सुनिश्चित नहीं कर रहे हैं उद्धृत करने के लिए चाहता हूँ नहीं करता ' t को उद्धृत करने की आवश्यकता है, क्योंकि आप कभी नहीं जानते कि उपयोगकर्ता कब में फेंक देगा Robert'; rm -rf /

यह समझने के लिए कि कवर के तहत क्या हो रहा है, आप दो छोटे सहायक कार्यों के साथ खेल सकते हैं:

debug_args() {
    for (( I=1; $I <= $#; I++ )); do
        echo -n "$I:<${!I}> " 1>&2
    done
    echo 1>&2
}

debug_args_and_run() {
    debug_args "$@"
    "$@"
}

इसे निष्पादित करने से पहले प्रत्येक तर्क को एक कमांड में रखा जाएगा:

$ debug_args_and_run echo a'"'b"'"c arg2
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

$ bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)"
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

$ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)")"
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'echo' 'a"b'"'"'c' 'arg2'> 
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

$ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)")")"
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'bash' '-c' ''"'"'debug_args_and_run'"'"' '"'"'echo'"'"' '"'"'a"b'"'"'"'"'"'"'"'"'c'"'"' '"'"'arg2'"'"''> 
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'echo' 'a"b'"'"'c' 'arg2'> 
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

$ bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run bash -c "$(quote_args debug_args_and_run echo a'"'b"'"c arg2)")")")"
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'bash' '-c' ''"'"'debug_args_and_run'"'"' '"'"'bash'"'"' '"'"'-c'"'"' '"'"''"'"'"'"'"'"'"'"'debug_args_and_run'"'"'"'"'"'"'"'"' '"'"'"'"'"'"'"'"'echo'"'"'"'"'"'"'"'"' '"'"'"'"'"'"'"'"'a"b'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'c'"'"'"'"'"'"'"'"' '"'"'"'"'"'"'"'"'arg2'"'"'"'"'"'"'"'"''"'"''> 
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'bash' '-c' ''"'"'debug_args_and_run'"'"' '"'"'echo'"'"' '"'"'a"b'"'"'"'"'"'"'"'"'c'"'"' '"'"'arg2'"'"''> 
1:<bash> 2:<-c> 3:<'debug_args_and_run' 'echo' 'a"b'"'"'c' 'arg2'> 
1:<echo> 2:<a"b'c> 3:<arg2> 
a"b'c arg2

हाय काइल। आपके समाधान ने मेरे पास एक मामले के लिए बहुत अच्छा काम किया, जब मुझे एक तर्क के रूप में तर्कों के एक समूह को पारित करने की आवश्यकता थी vagrant ssh -c {single-arg} guest:। {single-arg}एकल arg के रूप में व्यवहार किए जाने की आवश्यकता है क्योंकि अतिथि के नाम के रूप में योनि अगले arg लेता है। आदेश को बदला नहीं जा सकता। लेकिन मुझे एक कमांड और इसके तर्कों को पारित करने की आवश्यकता थी {single-arg}। इसलिए मैंने quote_args()कमांड और उसके आर्ग को कोट करने के लिए आपका उपयोग किया , और परिणाम के चारों ओर दोहरे उद्धरण लगाए, और यह एक आकर्षण की तरह काम किया vagrant ssh -c "'command' 'arg 1 with blanks' 'arg 2'" guest:। धन्यवाद!!!
एंड्रियास मैयर

6

IMHO असली जवाब यह है कि आप एकल-उद्धृत स्ट्रिंग्स के भीतर एकल-उद्धरण से बच नहीं सकते हैं।

यह नामुमकिन है।

अगर हम मान लें कि हम बैश का उपयोग कर रहे हैं।

बैश मैनुअल से ...

Enclosing characters in single quotes preserves the literal value of each
character within the quotes.  A single quote may not occur
between single quotes, even when preceded by a backslash.

आपको अन्य स्ट्रिंग एस्केप तंत्रों में से एक का उपयोग करने की आवश्यकता है "या \"

इसमें कुछ भी जादू नहीं है aliasकि यह एकल उद्धरणों का उपयोग करता है।

दोनों निम्नलिखित काम को कोसते हैं।

alias rxvt="urxvt -fg '#111111' -bg '#111111'"
alias rxvt=urxvt\ -fg\ \'#111111\'\ -bg\ \'#111111\'

बाद वाला स्पेस कैरेक्टर से बचने के लिए \ _ का उपयोग कर रहा है।

# 111111 के बारे में कुछ भी जादू नहीं है कि एकल उद्धरण की आवश्यकता है।

निम्नलिखित विकल्प उसी परिणाम को प्राप्त करते हैं जो अन्य दो विकल्पों में होता है, जिसमें rxvt उर्फ ​​अपेक्षित रूप से काम करता है।

alias rxvt='urxvt -fg "#111111" -bg "#111111"'
alias rxvt="urxvt -fg \"#111111\" -bg \"#111111\""

आप # परेशानियों से भी सीधे बच सकते हैं

alias rxvt="urxvt -fg \#111111 -bg \#111111"

"वास्तविक उत्तर यह है कि आप एकल-उद्धृत स्ट्रिंग्स के भीतर एकल-उद्धरण से बच नहीं सकते हैं।" यह तकनीकी रूप से सच है। लेकिन आपके पास एक समाधान हो सकता है जो एकल उद्धरण से शुरू होता है, एक उद्धरण के साथ समाप्त होता है, और केवल बीच में एकल उद्धरण होता है। stackoverflow.com/a/49063038
wisbucky

भागने से नहीं, केवल संगति से।
टेकनोपॉल

4

दिए गए उदाहरण में, केवल बाहरी उद्धरण तंत्र के रूप में एकल उद्धरण के बजाय दोहरे उद्धरण चिह्नों का उपयोग किया गया है:

alias rxvt="urxvt -fg '#111111' -bg '#111111'"

यह दृष्टिकोण कई मामलों के लिए उपयुक्त है जहां आप बस एक निश्चित स्ट्रिंग को एक कमांड में पास करना चाहते हैं: बस जांचें कि शेल एक के माध्यम से दोहरे-उद्धृत स्ट्रिंग की व्याख्या कैसे करेगा echo, और यदि आवश्यक हो तो बैकस्लैश वाले वर्णों से बच सकते हैं।

उदाहरण में, आप देखेंगे कि स्ट्रिंग की सुरक्षा के लिए दोहरे उद्धरण पर्याप्त हैं:

$ echo "urxvt -fg '#111111' -bg '#111111'"
urxvt -fg '#111111' -bg '#111111'

4

जाहिर है, बस दोहरे उद्धरण चिह्नों के साथ घेरना आसान होगा, लेकिन इसमें चुनौती कहां है? यहाँ केवल एक उद्धरण का उपयोग करके उत्तर दिया गया है। मैं इसके बजाय एक चर का उपयोग कर रहा हूं, aliasताकि सबूत के लिए प्रिंट करना आसान हो, लेकिन यह उपयोग करने के समान है alias

$ rxvt='urxvt -fg '\''#111111'\'' -bg '\''#111111'\'
$ echo $rxvt
urxvt -fg '#111111' -bg '#111111'

व्याख्या

कुंजी यह है कि आप एकल उद्धरण को बंद कर सकते हैं और इसे जितनी बार चाहें उतनी बार खोल सकते हैं। उदाहरण के लिए के foo='a''b'रूप में ही है foo='ab'। तो आप एकल उद्धरण को बंद कर सकते हैं, शाब्दिक एकल उद्धरण में फेंक सकते हैं \', फिर अगले एकल उद्धरण को फिर से खोल सकते हैं।

ब्रेकडाउन आरेख

यह आरेख ब्रैकेट्स का उपयोग करके यह स्पष्ट करता है कि एकल उद्धरण खोले और बंद किए गए हैं। उद्धरण "नेस्टेड" नहीं हैं जैसे कि कोष्ठक हो सकते हैं। आप रंग हाइलाइटिंग पर भी ध्यान दे सकते हैं, जो सही ढंग से लागू होता है। उद्धृत तार मैरून हैं, जबकि \'काला है।

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'    # original
[^^^^^^^^^^] ^[^^^^^^^] ^[^^^^^] ^[^^^^^^^] ^    # show open/close quotes
 urxvt -fg   ' #111111  '  -bg   ' #111111  '    # literal characters remaining

(यह मूल रूप से एड्रियन के रूप में एक ही उत्तर है, लेकिन मुझे लगता है कि यह इसे बेहतर ढंग से समझाता है। साथ ही उनके जवाब में अंत में 2 शानदार एकल उद्धरण हैं।)


+1 '\''विधि का उपयोग करने के लिए मैं उस विधि का उपयोग करता हूं '"'"'जो अक्सर मनुष्यों के पढ़ने के लिए कठिन होती है।
mtraceur

3

यहाँ ऊपर दिए गए एक सच्चे उत्तर पर विस्तार दिया गया है:

कभी-कभी मैं ss पर rsync का उपयोग करके डाउनलोड कर रहा हूँ और इसे 'TWICE' में फ़ाइल नाम से बचना होगा! (OMG!) एक बार बैश के लिए और एक बार ssh के लिए। प्रत्यावर्तन उद्धरण के एक ही सिद्धांत यहाँ काम पर है।

उदाहरण के लिए, मान लें कि हम प्राप्त करना चाहते हैं: लुईस थेरॉक्स की ला कहानियां ...

  1. सबसे पहले आप लुई थेरॉक्स को बैश के लिए सिंगल कोट्स में और डबल कोट्स के लिए संलग्न करें: '' लुई थेरॉक्स ''
  2. तब आप दोहरे उद्धरण '' '' से बचने के लिए सिंगल कोट्स का उपयोग करते हैं।
  3. एपोस्ट्रोफ "" से बचने के लिए दोहरे उद्धरण चिह्नों का उपयोग करें
  4. फिर # 2 दोहराएं, दोहरे उद्धरणों से बचने के लिए एकल उद्धरणों का उपयोग करते हुए '' ''
  5. फिर ला को स्टोरीज़ को बैश के लिए सिंगल कोट्स और ssh के लिए डबल कोट्स में संलग्न करें: '' 'ला स्टोरीज़' ''

और निहारना! आप इस के साथ हवा:

rsync -ave ssh '"Louis Theroux"''"'"'"'"''"s LA Stories"'

जो एक बहुत कम के लिए एक बहुत बड़ा काम है - लेकिन आप वहां जाते हैं


3
shell_escape () {
    printf '%s' "'${1//\'/\'\\\'\'}'"
}

कार्यान्वयन स्पष्टीकरण:

  • डबल कोट्स ताकि हम आसानी से सिंगल कोट्स को रैप करके आउटपुट और ${...}सिंटैक्स का उपयोग कर सकें

  • बैश की खोज और प्रतिस्थापित करने का तरीका ऐसा दिखता है: ${varname//search/replacement}

  • हम 'साथ बदल रहे हैं'\''

  • '\''एक 'जैसे सांकेतिक शब्दों में बदलना :

    1. ' एकल उद्धरण को समाप्त करता है

    2. \'सांकेतिक 'शब्दों में बदलना (बैकस्लैश की जरूरत है क्योंकि हम उद्धरण के अंदर नहीं हैं)

    3. ' फिर से एकल उद्धरण शुरू करता है

    4. बैश स्वचालित रूप से बीच में कोई सफेद स्थान के साथ तारों को समतल करता है

  • \हर एक से पहले है \और 'क्योंकि इसके लिए भागने के नियम हैं ${...//.../...}

string="That's "'#@$*&^`(@#'
echo "original: $string"
echo "encoded:  $(shell_escape "$string")"
echo "expanded: $(bash -c "echo $(shell_escape "$string")")"

PS हमेशा सिंगल उद्धृत स्ट्रिंग्स को एनकोड करता है क्योंकि वे डबल उद्धृत स्ट्रिंग्स की तुलना में सरल होते हैं।


2

नेस्टेड कोटेशन की कई परतों की समस्या को ठीक करने का एक और तरीका:

आप बहुत कम जगह में बहुत अधिक रटना करने की कोशिश कर रहे हैं, इसलिए बैश फ़ंक्शन का उपयोग करें।

समस्या यह है कि आप बहुत से स्तर के घोंसले के शिकार होने की कोशिश कर रहे हैं, और बुनियादी उर्फ ​​प्रौद्योगिकी को समायोजित करने के लिए पर्याप्त शक्तिशाली नहीं है। इस तरह से एक बाश फ़ंक्शन का उपयोग करें ताकि यह एकल, डबल उद्धरण वापस टिक और मापदंडों में पारित हो, सभी सामान्य रूप से नियंत्रित किए जाएंगे क्योंकि वे उम्मीद करेंगे:

lets_do_some_stuff() {
    tmp=$1                       #keep a passed in parameter.
    run_your_program $@          #use all your passed parameters.
    echo -e '\n-------------'    #use your single quotes.
    echo `date`                  #use your back ticks.
    echo -e "\n-------------"    #use your double quotes.
}
alias foobarbaz=lets_do_some_stuff

तो फिर आप अपने $ 1 और $ 2 चर और एकल, दोहरे उद्धरण चिह्नों और वापस टिक का उपयोग कर सकते हैं अलिया फ़ंक्शन के बारे में चिंता किए बिना उनकी अखंडता को बर्बाद कर रहे हैं।

यह कार्यक्रम प्रिंट करता है:

el@defiant ~/code $ foobarbaz alien Dyson ring detected @grid 10385
alien Dyson ring detected @grid 10385
-------------
Mon Oct 26 20:30:14 EDT 2015
-------------

2

यदि आपके पास जीएनयू समानांतर स्थापित है, तो आप इसकी आंतरिक बोली का उपयोग कर सकते हैं:

$ parallel --shellquote
L's 12" record
<Ctrl-D>
'L'"'"'s 12" record'
$ echo 'L'"'"'s 12" record'
L's 12" record

संस्करण 20190222 से आप --shellquoteकई बार भी कर सकते हैं :

$ parallel --shellquote --shellquote --shellquote
L's 12" record
<Ctrl-D>
'"'"'"'"'"'"'L'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'s 12" record'"'"'"'"'"'"'
$ eval eval echo '"'"'"'"'"'"'L'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'"'s 12" record'"'"'"'"'"'"'
L's 12" record

यह सभी समर्थित गोले में स्ट्रिंग को उद्धृत करेगा (न केवल bash)।


1

यह समारोह:

quote () 
{ 
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}

'अंदर उद्धृत करने की अनुमति देता है '। इस रूप में उपयोग करें:

$ quote "urxvt -fg '#111111' -bg '#111111'"
'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''

यदि उद्धरण के लिए लाइन अधिक जटिल हो जाती है, जैसे एकल उद्धरणों के साथ मिश्रित दोहरे उद्धरण, यह एक चर के अंदर उद्धृत करने के लिए स्ट्रिंग प्राप्त करने के लिए काफी मुश्किल हो सकता है। जब ऐसे मामले दिखाई देते हैं, तो सटीक लाइन लिखें जिसे आपको एक स्क्रिप्ट के अंदर उद्धृत करने की आवश्यकता है (इसके समान)।

#!/bin/bash

quote ()
{
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}

while read line; do
    quote "$line"
done <<-\_lines_to_quote_
urxvt -fg '#111111' -bg '#111111'
Louis Theroux's LA Stories
'single quote phrase' "double quote phrase"
_lines_to_quote_

उत्पादन होगा:

'urxvt -fg '\''#111111'\'' -bg '\''#111111'\'''
'Louis Theroux'\''s LA Stories'
''\''single quote phrase'\'' "double quote phrase"'

सभी सही ढंग से उद्धृत एकल उद्धरण के अंदर तार।


1

यदि आप पायथन 2 या पायथन 3 के भीतर शेल स्ट्रिंग उत्पन्न कर रहे हैं, तो निम्नलिखित तर्क देने में मदद कर सकते हैं:

#!/usr/bin/env python

from __future__ import print_function

try:  # py3
    from shlex import quote as shlex_quote
except ImportError:  # py2
    from pipes import quote as shlex_quote

s = """foo ain't "bad" so there!"""

print(s)
print(" ".join([shlex_quote(t) for t in s.split()]))

यह आउटपुट होगा:

foo ain't "bad" so there!
foo 'ain'"'"'t' '"bad"' so 'there!'

1

यहाँ मेरे दो सेंट हैं - अगर कोई चाहता है कि sh-पोर्टेबल हो, तो न सिर्फ -स्पेक्ट्रिक bash(समाधान बहुत कुशल नहीं है, हालांकि, क्योंकि यह एक बाहरी कार्यक्रम शुरू करता है - sed):

  • इसे quote.sh(या सिर्फ quote) अपने कहीं पर रखें PATH:
# यह मानक इनपुट (स्टडिन) के साथ काम करता है
बोली () {
  इको-एन "" ";
  sed 's / \ ([' '' '' '] [' '' '' '* * \ _' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'को घसीटते हुए' '' '' '' '' '' '' '' '' '' '' ':' '' '' '' '' '' '' '' '' '' ''।
  इको-एन ""
}

मामले में "$ 1"
 -) उद्धरण ;;
 *) प्रतिध्वनि "उपयोग: बिल्ली ... | उद्धरण - बॉर्न शेल के लिए # एकल-उद्धरण इनपुट" 2> & 1 ;;
esac

एक उदाहरण:

$ इको-एन "जी'डे, मेट!" | ./quote.sh
'आपका दिन शुभ हो!'

और, ज़ाहिर है, कि वापस धर्मान्तरित:

$ गूंज 'जी' '' '' दिन, दोस्त! ''
आपका दिन शुभ हो!

स्पष्टीकरण: मूल रूप से हमें इनपुट को उद्धरण के साथ संलग्न करना होगा ', और फिर इस माइक्रो-मॉन्स्टर के साथ किसी एक उद्धरण को भी बदलना होगा: '"'"'(एक उद्धरण के साथ उद्घाटन उद्धरण को समाप्त करें ', दोहरे उद्धरण के साथ लपेटकर पाया गया एकल उद्धरण से बच जाएं - "'"और, तो अंत में एक नया उद्घाटन एकल उद्धरण जारी ', या छद्म अंकन में: ' + "'" + ' == '"'"')

sedनिम्न प्रतिस्थापन कमांड के साथ उपयोग करने के लिए एक मानक तरीका है :

s/\(['][']*\)/'"\1"'/g 

एक छोटी सी समस्या, हालांकि, यह है कि शेल में उपयोग करने के लिए किसी को इन सभी एकल उद्धरण वर्णों को सेड एक्सप्रेशन में ही भागने की जरूरत है - क्या कुछ की ओर जाता है

sed 's/\(['"'"']['"'"']*\)/'"'"'"\1"'"'"'/g' 

(और इस परिणाम को बनाने का एक अच्छा तरीका s/\(['][']*\)/'"\1"'/gकाइल रोज़ 'या जॉर्ज वी। रेली की लिपियों की मूल अभिव्यक्ति को खिलाना है )।

अंत में, यह इनपुट से आने की उम्मीद करने के लिए समझ में आता है stdin- क्योंकि इसे कमांड-लाइन तर्कों के माध्यम से पारित करने से पहले से ही बहुत अधिक परेशानी हो सकती है।

(ओह, और हो सकता है कि हम एक छोटी सी मदद संदेश जोड़ना चाहते हों, ताकि स्क्रिप्ट तब न लटक जाए जब कोई उसे सिर्फ यह ./quote.sh --helpसोचकर चलाए कि वह क्या करता है।)


0

यहाँ एक और उपाय है। यह फ़ंक्शन एकल तर्क लेगा और उचित रूप से एकल-उद्धरण वर्ण का उपयोग करके इसे उद्धृत करेगा, जैसा कि ऊपर दिए गए मतदान उत्तर बताते हैं:

single_quote() {
  local quoted="'"
  local i=0
  while [ $i -lt ${#1} ]; do
    local ch="${1:i:1}"
    if [[ "$ch" != "'" ]]; then
      quoted="$quoted$ch"
    else
      local single_quotes="'"
      local j=1
      while [ $j -lt ${#1} ] && [[ "${1:i+j:1}" == "'" ]]; do
        single_quotes="$single_quotes'"
        ((j++))
      done
      quoted="$quoted'\"$single_quotes\"'"
      ((i+=j-1))
    fi
    ((i++))
  done
  echo "$quoted'"
}

तो, आप इसे इस तरह से उपयोग कर सकते हैं:

single_quote "1 2 '3'"
'1 2 '"'"'3'"'"''

x="this text is quoted: 'hello'"
eval "echo $(single_quote "$x")"
this text is quoted: 'hello'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.