&& और | के बीच क्या अंतर है बैश स्क्रिप्ट में?


13

आइए नीचे दो लाइनें लें जो हमें दो अलग-अलग परिणाम देते हैं।

p=$(cd ~ && pwd) ; echo $p
p=$(cd ~ |  pwd) ; echo $p

दोनों अलग कैसे हैं?


@ हेमायल धन्यवाद क्या आप मेरे मामले पर मतभेद निकाल सकते हैं? धन्यवाद।
नाम जी वीयू

1
संकेत:| उपधाराओं में चलाने के दोनों ओर आदेश ।
हेमायल

जवाबों:


21

में p=$(cd ~ && pwd):

  • कमांड सबस्टेशन, $()एक उपधारा में चलता है

  • cd ~निर्देशिका ~(अपने घर) में परिवर्तन , अगर cdसफल होता है ( &&) तब pwdSTDOUT पर निर्देशिका नाम प्रिंट करता है, इसलिए सहेजे गए स्ट्रिंग pआपके घर की निर्देशिका होगी जैसे/home/foobar

में p=$(cd ~ | pwd):

  • फिर से $()एक उपधारा को जन्म देती है

  • |संबंधित उपधाराओं में दोनों तरफ के कमांड (और दोनों एक ही समय में शुरू होते हैं)

  • तो cd ~यह एक सबशेल में किया जाता है, और pwdएक अलग सब्सक्रिप्शन में

  • इसलिए आपको केवल STDOUT मिलेगा pwd, जहां से आप कमांड चलाते हैं, यह कोई भी निर्देशिका हो सकती है जैसा कि आप कल्पना कर सकते हैं, इसलिए pइसमें निर्देशिका का नाम होगा जहां से कमांड को इनवॉइस किया गया है, न कि आपके होम डायरेक्टरी से


कमांड के बीच पाइप का उद्देश्य क्या है? cd ~कोई आउटपुट नहीं देता है, और pwdकोई इनपुट नहीं पढ़ता है।
बरमार

दूसरी आज्ञा अनिवार्य रूप से (cd ~);p=$(pwd)नहीं के बराबर है?
बामर

@ बरमर हां, यह वही है जो ओपी ने इस्तेमाल किया है, और मैं सिर्फ उसके लिए समझा रहा हूं।
हेमायल

7

मुख्य मुद्दा यह है कि ऑपरेटर कैसे &&और |दो कमांड को जोड़ते हैं।

&&बाहर निकलने के कोड के माध्यम से आदेशों को जोड़ता है। |फ़ाइल वर्णनकर्ता (stdin, stdout) के माध्यम से दो आदेशों को जोड़ता है।

पहले सरल करें। हम असाइनमेंट निकाल सकते हैं और लिख सकते हैं:

echo $(cd ~ && pwd)
echo $(cd ~ | pwd)

हम इसका विश्लेषण करने के लिए कमांड निष्पादन उप शेल भी निकाल सकते हैं:

$ cd ~ && pwd
$ cd ~ | pwd

&&

यदि हम उस कमांड को निष्पादित करने के लिए प्रॉम्प्ट को बदलते हैं, जहां कमांड निष्पादित होते हैं, तो कुछ ऐसा PS1='\w\$ ', हम इसे देखेंगे:

/tmp/user$ cd ~ && pwd
/home/user
~$ 
  • कमांड cd ~"निष्पादित निर्देशिका" को वास्तविक उपयोगकर्ता के घर में बदल देता है जो कमांड निष्पादित कर रहा है ( /home/user)।
  • जैसे ही कमांड का परिणाम सफल हुआ (कोड से बाहर निकलें), && निष्पादित होने के बाद अगला कमांड
  • और "वर्तमान कार्यशील निर्देशिका" मुद्रित है।
  • चल खोल इसकी बदल गया है pwdकरने के लिए ~के रूप में की शीघ्र से दिखाया गया है ~$

यदि किसी कारण से निर्देशिका का परिवर्तन असफल हो गया था (निकास कोड नहीं 0) तो (निर्देशिका मौजूद नहीं है, निर्देशिका को पढ़ने की अनुमति रोकती है) अगली कमांड निष्पादित नहीं की जाएगी।

उदाहरण:

/tmp/user$ false && pwd
/tmp/user$ _ 

1 से बाहर निकलने का कोड falseअगले कमांड के निष्पादन को रोकता है।

इस प्रकार, "कमांड 1" का निकास कोड "कमांड 2" को प्रभावित करता है।

अब, पूरे कमांड के प्रभाव:

/tmp/user$ echo $(cd ~ && pwd)
/home/user
/tmp/user$ _

निर्देशिका को बदल दिया गया था, लेकिन एक उप-शेल के अंदर $(…), परिवर्तित निर्देशिका मुद्रित होती है /home/user, लेकिन उप-शेल बंद होने के तुरंत बाद छोड़ दी जाती है। Pwd प्रारंभिक निर्देशिका ( /tmp/user) है।

|

ऐसा ही होता है:

/tmp/user$ cd ~ | pwd
/tmp/user
/tmp/user$ _

मेटा-कैरेक्टर |(एक सच्चा ऑपरेटर नहीं) शेल बनाने के लिए संकेत देता है कि जिसे "पाइप" कहा जाता है, (बश में) पाइप के प्रत्येक तरफ प्रत्येक कमांड ( |) प्रत्येक सब-शेल के अंदर सेट होता है, पहले राइट साइड कमान, फिर, एक छोड़ दिया। /dev/stdinराइट कमांड का इनपुट फाइल डिस्क्रिप्टर आउटपुट डिस्क्रिप्टर ( /dev/stdout) से जुड़ा है और फिर दोनों कमांड्स को शुरू करने और बातचीत करने के लिए छोड़ा गया है। बाएं कमांड ( cd -) का कोई आउटपुट नहीं है, और, सही कमांड ( pwd) भी इनपुट को स्वीकार नहीं करता है। इसलिए, प्रत्येक एक स्वतंत्र रूप से प्रत्येक उप-शेल के अंदर चलता है।

  • cd ~एक खोल के लोक निर्माण विभाग बदल जाता है।
  • pwd(पूरी तरह से स्वतंत्र) अन्य उप खोल के लोक निर्माण विभाग प्रिंट करता है।

प्रत्येक शेल पर परिवर्तन समाप्त हो जाते हैं जब पाइप समाप्त होता है, तो बाहरी उप-शेल ने पीडब्ल्यूडी को नहीं बदला है।

इसीलिए दोनों कमांड केवल "फाइल डिस्क्रिप्टर" से जुड़े हैं।
इस मामले में, कुछ भी नहीं भेजा गया है, और कुछ भी नहीं पढ़ा है।

पूरी कमांड:

$ echo "$(cd ~ | pwd)"

केवल उस निर्देशिका को प्रिंट करेगा जहां कमांड निष्पादित किया गया था।


5

मुझे यकीन नहीं है अगर आपका मतलब है '|' या '||' आपके दूसरे मामले में।

'|' एक शेल में एक कमांड का आउटपुट दूसरे के इनपुट पर होता है - एक सामान्य उपयोग का मामला कुछ इस प्रकार है: curl http://abcd.com/efgh | grep ijkl अर्थात एक कमांड को रन करें, और कमांड के आउटपुट को प्रोसेस करने के लिए किसी अन्य कमांड का उपयोग करें।

आपके द्वारा दिए गए उदाहरण में, यह काफी गैर-निरर्थक है, क्योंकि 'सीडी' आमतौर पर कोई आउटपुट नहीं देता है, और 'pwd' किसी इनपुट की उम्मीद नहीं करता है।

'&&' और '|| हालांकि साथी आदेश हैं। वे तार्किक और "और" या "अधिकांश" भाषाओं में ऑपरेटरों के समान उपयोग करने के लिए डिज़ाइन किए गए हैं। हालांकि, जो अनुकूलन किए जाते हैं, वे उन्हें एक विशिष्ट व्यवहार देते हैं जो शेल प्रोग्रामिंग प्रतिमान है।

एक तार्किक "और" ऑपरेशन के परिणाम को निर्धारित करने के लिए, आपको केवल दूसरी स्थिति का मूल्यांकन करने की आवश्यकता है यदि पहली शर्त सफल होती है - यदि पहली शर्त विफल हो जाती है, तो समग्र परिणाम हमेशा गलत होगा।

एक तार्किक "या" ऑपरेशन के परिणाम को निर्धारित करने के लिए, आपको केवल दूसरी स्थिति का मूल्यांकन करने की आवश्यकता है यदि पहली शर्त विफल हो जाती है - यदि पहली स्थिति सफल होती है, तो समग्र परिणाम हमेशा सही होगा।

इसलिए, शेल में, यदि आपके पास command1 && command2 command2केवल तभी निष्पादित किया जाएगा जब command1पूरा हो गया है और एक सफल परिणाम कोड लौटाया है। यदि आप एक विफलता कोड देता है, तो पूरा command1 || command2 command2होने पर निष्पादित किया जाएगा ।command1command1

एक अन्य सामान्य प्रतिमान के लिए command1एक परीक्षण कमांड होना चाहिए - यह एक एकल लाइन उत्पन्न करता है यदि / तो कथन - उदाहरण के लिए:

[ "$VAR" = "" ] && VAR="Value if empty"

यदि यह वर्तमान में रिक्त है तो किसी चर को मान प्रदान करने का एक लंबा (लंबा घुमावदार) तरीका है।

Stack Exchange पर इस प्रक्रिया के उपयोग के कई उदाहरण हैं

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