उद्धृत करने के कई स्तरों (वास्तव में, पार्सिंग / व्याख्या के कई स्तरों) से निपटना जटिल हो सकता है। यह कुछ बातों को ध्यान में रखने में मदद करता है:
- प्रत्येक "उद्धृत करने का स्तर" संभवतः एक अलग भाषा को शामिल कर सकता है।
- भाषा द्वारा उद्धरण नियम भिन्न होते हैं।
- जब एक या दो से अधिक नेस्टेड स्तरों के साथ काम करते हैं, तो आमतौर पर "नीचे से ऊपर, ऊपर" (यानी सबसे बाहरी तक) काम करना सबसे आसान होता है।
कोटेशन का स्तर
आइए हम आपके उदाहरण आदेशों को देखें।
pgrep -fl java | grep -i datanode | awk '{print $1}'
आपका पहला उदाहरण कमांड (ऊपर) चार भाषाओं का उपयोग करता है: आपका खोल, pgrep में regex, grep में regex (जो pgrep में regex भाषा से भिन्न हो सकता है ), और awk । इसमें शामिल व्याख्या के दो स्तर हैं: शेल और शामिल कमांड के प्रत्येक के लिए शेल के बाद का एक स्तर। उद्धृत करने का केवल एक ही स्पष्ट स्तर है (शेल को awk में उद्धृत करना )।
ssh host …
इसके बाद आपने शीर्ष पर ssh का स्तर जोड़ा । यह प्रभावी रूप से एक और शेल स्तर है: ssh स्वयं कमांड की व्याख्या नहीं करता है, यह इसे दूरस्थ छोर (जैसे (जैसे) पर एक शेल को सौंपता है sh -c …
और यह शेल स्ट्रिंग की व्याख्या करता है।
ssh host "sudo su user -c …"
फिर आपने सु ( सूडो के माध्यम से , जो इसके कमांड तर्कों की व्याख्या नहीं करता है, का उपयोग करके बीच में एक और शेल स्तर जोड़ने के बारे में पूछा , इसलिए हम इसे अनदेखा कर सकते हैं)। इस बिंदु पर, आपके पास नेस्टिंग के तीन स्तर हैं ( awk → shell, shell → shell ( ssh ), shell → shell ( su user -c ), इसलिए मैं "नीचे, ऊपर" दृष्टिकोण का उपयोग करने की सलाह देता हूं। मैं यह मान लूंगा। अपने गोले बॉर्न संगत (जैसे हैं श , राख , पानी का छींटा , ksh , बैश , zsh , आदि)। खोल (के कुछ अन्य प्रकार मछली , आर सीआदि) अलग सिंटैक्स की आवश्यकता हो सकती है, लेकिन विधि अभी भी लागू होती है।
नीचे से ऊपर
- उस स्ट्रिंग को तैयार करें जिसे आप अंतरतम स्तर पर प्रस्तुत करना चाहते हैं।
- अगली-उच्चतम भाषा के उद्धरण प्रदर्शनों के एक उद्धरण तंत्र का चयन करें।
- अपने चयनित उद्धृत तंत्र के अनुसार वांछित स्ट्रिंग को कोट करें।
- अक्सर कई भिन्नताएं होती हैं कि किस तरह के तंत्र को लागू करना है। इसे हाथ से करना आमतौर पर अभ्यास और अनुभव का विषय है। जब इसे प्रोग्रामिक रूप से किया जाता है, तो आमतौर पर सही पाने के लिए सबसे आसान चुनना सबसे अच्छा होता है (आमतौर पर "सबसे शाब्दिक" (कम से कम पलायन))।
- वैकल्पिक रूप से, अतिरिक्त कोड के साथ परिणामी स्ट्रिंग का उपयोग करें।
- यदि आप अभी तक उद्धृत / व्याख्या के अपने वांछित स्तर तक नहीं पहुंचे हैं, तो परिणामी उद्धृत स्ट्रिंग (प्लस कोई भी जोड़ा गया कोड) लें और इसे चरण 2 में शुरुआती स्ट्रिंग के रूप में उपयोग करें।
शब्दार्थ वारि को उद्धृत करना
यहां ध्यान रखने वाली बात यह है कि प्रत्येक भाषा (कोटिंग लेवल) एक ही कोटिंग कैरेक्टर को थोड़ा अलग शब्दार्थ (या यहां तक कि बहुत अलग शब्दार्थ) दे सकती है।
अधिकांश भाषाओं में एक "शाब्दिक" उद्धृत तंत्र है, लेकिन वे वास्तव में कितने शाब्दिक हैं। बॉर्न जैसे गोले का एकल उद्धरण वास्तव में शाब्दिक है (जिसका अर्थ है कि आप इसका उपयोग एकल उद्धरण चरित्र को उद्धृत करने के लिए नहीं कर सकते हैं)। अन्य भाषाओं (पर्ल, रूबी) कि वे व्याख्या में कम शाब्दिक हैं कुछ भी उद्धृत क्षेत्रों के अंदर बैकस्लैश दृश्यों गैर शाब्दिक (विशेष रूप से, \\
और \'
में परिणाम \
और '
है, लेकिन अन्य बैकस्लैश दृश्यों वास्तव में शाब्दिक हैं)।
आपको इसके उद्धरण नियमों और समग्र वाक्यविन्यास को समझने के लिए अपनी प्रत्येक भाषा के लिए दस्तावेज़ीकरण पढ़ना होगा।
आपका उदाहरण
आपके उदाहरण का अंतरतम स्तर एक अजीब कार्यक्रम है।
{print $1}
आप इसे शेल कमांड लाइन में एम्बेड करने जा रहे हैं:
pgrep -fl java | grep -i datanode | awk …
हमें कम से कम (कम से कम) अंतरिक्ष और जाग कार्यक्रम $
में रक्षा करने की आवश्यकता है । स्पष्ट विकल्प पूरे कार्यक्रम के आसपास शेल में एकल उद्धरण का उपयोग करना है।
हालांकि अन्य विकल्प भी हैं:
{print\ \$1}
सीधे अंतरिक्ष से बचो और $
{print' $'1}
एकल उद्धरण केवल स्थान और $
"{print \$1}"
डबल पूरी बोली और बच निकले $
{print" $"1}
डबल कोट्स केवल स्पेस है और $
यह नियमों को थोड़ा झुका सकता है ( $
डबल कोटेड स्ट्रिंग के अंत में अनसैप्ड) शाब्दिक है, लेकिन यह अधिकांश गोले में काम करने लगता है।
यदि प्रोग्राम खुले और बंद घुंघराले ब्रेसिज़ के बीच एक अल्पविराम का उपयोग करता है तो हमें कुछ गोले में "ब्रेस विस्तार" से बचने के लिए कॉमा या घुंघराले ब्रेस को भी उद्धृत या बचाना होगा।
हम '{print $1}'
इसे बाकी "खोल" कोड में एम्बेड करते हैं:
pgrep -fl java | grep -i datanode | awk '{print $1}'
इसके बाद, आप इसे su और sudo के माध्यम से चलाना चाहते थे ।
sudo su user -c …
su user -c …
ऐसा ही है some-shell -c …
(कुछ अन्य यूआईडी के तहत चलने के अलावा), इसलिए सु सिर्फ एक और शेल स्तर जोड़ता है। सुडो अपने तर्कों की व्याख्या नहीं करता है, इसलिए यह किसी भी उद्धरण स्तर को नहीं जोड़ता है।
हमें अपने कमांड स्ट्रिंग के लिए एक और शेल स्तर की आवश्यकता है। हम फिर से एकल उद्धरण चुन सकते हैं, लेकिन हमें मौजूदा एकल उद्धरणों को विशेष संभालना होगा। सामान्य तरीका इस तरह दिखता है:
'pgrep -fl java | grep -i datanode | awk '\''{print $1}'\'
यहां चार तार हैं जो शेल व्याख्या करेगा और संक्षिप्त करेगा: पहला एकल उद्धृत स्ट्रिंग ( pgrep … awk
), एक बची हुई एकल बोली, एकल-उद्धृत awk प्रोग्राम, एक और बची हुई एकल उद्धरण।
बेशक, कई विकल्प हैं:
pgrep\ -fl\ java\ \|\ grep\ -i\ datanode\ \|\ awk\ \'{print\ \$1}
सब कुछ महत्वपूर्ण है
pgrep\ -fl\ java\|grep\ -i\ datanode\|awk\ \'{print\$1}
वही, लेकिन शानदार व्हाट्सएप के बिना (यहां तक कि awk प्रोग्राम में भी!)
"pgrep -fl java | grep -i datanode | awk '{print \$1}'"
डबल पूरी बात बोली, बचो $
'pgrep -fl java | grep -i datanode | awk '"'"'{print \$1}'"'"
आपकी भिन्नता; बच निकलने के बजाय दोहरे उद्धरण चिह्नों (दो वर्णों) का उपयोग करने के कारण सामान्य तरीके से थोड़ा लंबा
पहले स्तर में अलग-अलग उद्धरण का उपयोग करना इस स्तर पर अन्य विविधताओं के लिए अनुमति देता है:
'pgrep -fl java | grep -i datanode | awk "{print \$1}"'
'pgrep -fl java | grep -i datanode | awk {print\ \$1}'
Sudo / * su * कमांड लाइन में पहला वेरिएशन एंबेड करते हुए यह दें:
sudo su user -c 'pgrep -fl java | grep -i datanode | awk '\''{print $1}'\'
आप किसी अन्य एकल शेल स्तर संदर्भों (उदाहरण ssh host …
) में उसी स्ट्रिंग का उपयोग कर सकते हैं ।
इसके बाद, आपने शीर्ष पर ssh का स्तर जोड़ा । यह प्रभावी रूप से एक और शेल स्तर है: ssh स्वयं कमांड की व्याख्या नहीं करता है, लेकिन यह इसे दूरस्थ छोर (थ्रू) (जैसे) पर एक शेल को सौंपता है sh -c …
और यह शेल स्ट्रिंग की व्याख्या करता है।
ssh host …
प्रक्रिया समान है: स्ट्रिंग लें, एक उद्धरण विधि चुनें, इसका उपयोग करें, इसे एम्बेड करें।
एकल उद्धरणों का फिर से उपयोग करना:
'sudo su user -c '\''pgrep -fl java | grep -i datanode | awk '\'\\\'\''{print $1}'\'\\\'
अब ग्यारह तार हैं जिनकी व्याख्या की गई है और संक्षिप्त किया गया है: 'sudo su user -c '
एकल उद्धरण से 'pgrep … awk '
बच गए, एकल उद्धरण से बच गए, बैकस्लैश से बच गए, दो से बच गए एकल उद्धरण, एकल उद्धृत ऑक प्रोग्राम, एक बच गए एकल उद्धरण, एक बच गए बैकलैश, और एक अंतिम एकल उद्धरण से बच गए। ।
अंतिम रूप इस तरह दिखता है:
ssh host 'sudo su user -c '\''pgrep -fl java | grep -i datanode | awk '\'\\\'\''{print $1}'\'\\\'
यह हाथ से टाइप करने के लिए थोड़ा सा बोझिल है, लेकिन शेल के एकल उद्धरण के शाब्दिक स्वरूप से थोड़ी भिन्नता को स्वचालित करना आसान हो जाता है:
#!/bin/sh
sq() { # single quote for Bourne shell evaluation
# Change ' to '\'' and wrap in single quotes.
# If original starts/ends with a single quote, creates useless
# (but harmless) '' at beginning/end of result.
printf '%s\n' "$*" | sed -e "s/'/'\\\\''/g" -e 1s/^/\'/ -e \$s/\$/\'/
}
# Some shells (ksh, bash, zsh) can do something similar with %q, but
# the result may not be compatible with other shells (ksh uses $'...',
# but dash does not recognize it).
#
# sq() { printf %q "$*"; }
ap='{print $1}'
s1="pgrep -fl java | grep -i datanode | awk $(sq "$ap")"
s2="sudo su user -c $(sq "$s1")"
ssh host "$(sq "$s2")"