बीच क्या अंतर है <<
, <<<
और < <
पार्टी में?
बीच क्या अंतर है <<
, <<<
और < <
पार्टी में?
जवाबों:
यहाँ दस्तावेज़
<<
here-document
संरचना के रूप में जाना जाता है। आप प्रोग्राम को यह बताते हैं कि समाप्त पाठ क्या होगा, और जब भी उस सीमांकक को देखा जाएगा, तो प्रोग्राम आपके द्वारा दिए गए सभी सामान को इनपुट के रूप में पढ़ेगा और उस पर कार्य करेगा।
यहाँ मेरा मतलब है:
$ wc << EOF
> one two three
> four five
> EOF
2 5 24
इस उदाहरण में हम wc
प्रोग्राम को EOF
स्ट्रिंग के लिए प्रतीक्षा करने के लिए कहते हैं , फिर पांच शब्दों में टाइप करें, और फिर EOF
संकेत दें कि हम इनपुट दे रहे हैं। वास्तव में, यह wc
खुद से चलने , शब्दों में टाइप करने, फिर दबाने के समान हैCtrlD
बैश में ये अस्थायी फ़ाइलों के माध्यम से लागू होते हैं, आमतौर पर फॉर्म में /tmp/sh-thd.<random string>
, जबकि डैश में उन्हें गुमनाम पाइप के रूप में लागू किया जाता है। यह strace
कमांड के साथ ट्रेसिंग सिस्टम कॉल के माध्यम से देखा जा सकता है । बदलें bash
के साथ sh
कैसे को देखने के लिए /bin/sh
इस पुनर्निर्देशन प्रदर्शन करती है।
$ strace -e open,dup2,pipe,write -f bash -c 'cat <<EOF
> test
> EOF'
यहाँ स्ट्रिंग
<<<
के रूप में जाना जाता है here-string
। पाठ में टाइप करने के बजाय, आप एक कार्यक्रम के लिए पाठ के पूर्व-निर्मित स्ट्रिंग देते हैं। उदाहरण के लिए, इस तरह के कार्यक्रम के साथ ही bc
हम bc <<< 5*4
उस विशिष्ट मामले के लिए उत्पादन प्राप्त करने के लिए कर सकते हैं , कोई आवश्यकता नहीं है कि अंतःक्रियात्मक तरीके से बीसी चलाएं।
यहां बैश में स्ट्रिंग्स को अस्थायी फ़ाइलों के माध्यम से लागू किया जाता है, आमतौर पर प्रारूप में /tmp/sh-thd.<random string>
, जिन्हें बाद में अनलिंक किया जाता है, इस प्रकार उन्हें कुछ मेमोरी स्पेस पर अस्थायी रूप से कब्जा कर लिया जाता है, लेकिन /tmp
निर्देशिका प्रविष्टियों की सूची में दिखाई नहीं देते हैं, और प्रभावी रूप से अनाम फ़ाइलों के रूप में मौजूद होते हैं, जो अभी भी हो सकते हैं शेल द्वारा फ़ाइल डिस्क्रिप्टर के माध्यम से संदर्भित किया जा सकता है, और उस फाइल डिस्क्रिप्टर को कमांड द्वारा विरासत में प्राप्त किया जा रहा है और बाद में dup2()
फ़ंक्शन के माध्यम से फाइल डिस्क्रिप्टर 0 (स्टडिन) पर डुप्लिकेट किया गया है। इसके माध्यम से देखा जा सकता है
$ ls -l /proc/self/fd/ <<< "TEST"
total 0
lr-x------ 1 user1 user1 64 Aug 20 13:43 0 -> /tmp/sh-thd.761Lj9 (deleted)
lrwx------ 1 user1 user1 64 Aug 20 13:43 1 -> /dev/pts/4
lrwx------ 1 user1 user1 64 Aug 20 13:43 2 -> /dev/pts/4
lr-x------ 1 user1 user1 64 Aug 20 13:43 3 -> /proc/10068/fd
और ट्रेसिंग सिसल्स के माध्यम से (आउटपुट पठनीयता के लिए छोटा हो गया; ध्यान दें कि अस्थायी फाइल को fd 3 के रूप में कैसे खोला जाता है, इसे लिखा गया डेटा, फिर इसे O_RDONLY
fd 4 के रूप में ध्वज के साथ फिर से खोला जाता है और बाद में अनलिंक किया जाता है, फिर dup2()
fd 0 पर, जिसे cat
बाद में विरासत में मिला है। ):
$ strace -f -e open,read,write,dup2,unlink,execve bash -c 'cat <<< "TEST"'
execve("/bin/bash", ["bash", "-c", "cat <<< \"TEST\""], [/* 47 vars */]) = 0
...
strace: Process 10229 attached
[pid 10229] open("/tmp/sh-thd.uhpSrD", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
[pid 10229] write(3, "TEST", 4) = 4
[pid 10229] write(3, "\n", 1) = 1
[pid 10229] open("/tmp/sh-thd.uhpSrD", O_RDONLY) = 4
[pid 10229] unlink("/tmp/sh-thd.uhpSrD") = 0
[pid 10229] dup2(4, 0) = 0
[pid 10229] execve("/bin/cat", ["cat"], [/* 47 vars */]) = 0
...
[pid 10229] read(0, "TEST\n", 131072) = 5
[pid 10229] write(1, "TEST\n", 5TEST
) = 5
[pid 10229] read(0, "", 131072) = 0
[pid 10229] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=10229, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
+++ exited with 0 +++
राय: संभावित रूप से क्योंकि यहाँ तार अस्थायी पाठ फ़ाइलों का उपयोग करते हैं, यह संभव कारण है कि यहाँ-तार हमेशा एक अनुगामी नई पंक्ति सम्मिलित करते हैं, क्योंकि POSIX परिभाषा द्वारा पाठ फ़ाइल में लाइनें हैं जो newline वर्ण में समाप्त होती हैं।
प्रक्रिया प्रतिस्थापन
के रूप में tldp.org बताते हैं,
प्रक्रिया प्रतिस्थापन एक प्रक्रिया (या प्रक्रियाओं) के उत्पादन को दूसरी प्रक्रिया के स्टैडेन में फीड करता है।
तो प्रभाव में इस पाइप के समान है stdout , दूसरे के लिए एक आदेश के जैसे echo foobar barfoo | wc
। लेकिन ध्यान दें: बैश मैनपेज में आप देखेंगे कि इसे इस रूप में दर्शाया गया है <(list)
। तो मूल रूप से आप कई (!) कमांड के आउटपुट को रीडायरेक्ट कर सकते हैं।
नोट: तकनीकी रूप से जब आप कहते हैं कि < <
आप एक चीज़ का जिक्र नहीं कर रहे हैं, लेकिन एकल <
और प्रक्रिया से दो पुनर्निर्देशन से आउटपुट का पुनर्निर्देशन <( . . .)
।
अब क्या होता है अगर हम सिर्फ प्रतिस्थापन की प्रक्रिया करते हैं?
$ echo <(echo bar)
/dev/fd/63
जैसा कि आप देख सकते हैं, शेल अस्थायी फ़ाइल डिस्क्रिप्टर बनाता है /dev/fd/63
जहां आउटपुट जाता है (जो गाइल्स के उत्तर के अनुसार , एक अनाम पाइप है)। इसका मतलब <
है कि एक कमांड में इनपुट के रूप में फाइल डिस्क्रिप्टर को रीडायरेक्ट करता है।
बहुत सरल उदाहरण के लिए दो गूंज कमांड से आउटपुट की प्रक्रिया प्रतिस्थापन को wc में बनाना होगा:
$ wc < <(echo bar;echo foo)
2 2 8
तो यहाँ हम शेल बनाते हैं जो कोष्ठक में होने वाले सभी आउटपुट के लिए एक फाइल डिस्क्रिप्टर बनाता है और इनपुट के wc
रूप में पुनर्निर्देशित करता है । जैसा कि अपेक्षित है, wc को दो इको कमांड से वह स्ट्रीम प्राप्त होती है, जो स्वयं दो लाइनों को आउटपुट करेगा, प्रत्येक में एक शब्द होगा। और उचित रूप से हमारे पास 2 शब्द, 2 पंक्तियाँ, और 6 अक्षर और दो नए वर्ण हैं।
साइड नोट: प्रक्रिया प्रतिस्थापन को बशीवाद के रूप में संदर्भित किया जा सकता है (जैसे उन्नत गोले में प्रयोग करने योग्य एक कमांड या संरचना bash
, लेकिन POSIX द्वारा निर्दिष्ट नहीं), लेकिन इसे ksh मैन पेज और इस उत्तर सुझाव के ksh
रूप में बैश के अस्तित्व से पहले लागू किया गया था । गोले की तरह और हालांकि प्रक्रिया प्रतिस्थापन नहीं है। तो हम प्रक्रिया प्रतिस्थापन के बिना किसी अन्य कमांड में कई कमांड के आउटपुट को पुनर्निर्देशित कैसे कर सकते हैं? ग्रुपिंग प्लस पाइपिंग!tcsh
mksh
$ (echo foo;echo bar) | wc
2 2 8
प्रभावी रूप से यह उपरोक्त उदाहरण के समान है, हालांकि, यह प्रक्रिया प्रतिस्थापन से हुड के तहत अलग है, क्योंकि हम wc
पाइप के साथ जुड़े पूरे उपधारा और स्टड के स्टडआउट बनाते हैं । दूसरी ओर, प्रक्रिया प्रतिस्थापन एक कमांड को एक अस्थायी फ़ाइल डिस्क्रिप्टर पढ़ता है।
इसलिए यदि हम पाइपिंग के साथ समूहन कर सकते हैं, तो हमें प्रक्रिया प्रतिस्थापन की आवश्यकता क्यों है? क्योंकि कभी-कभी हम पाइपिंग का उपयोग नहीं कर सकते हैं। नीचे दिए गए उदाहरण पर विचार करें - दो कमांड्स के आउटपुट की तुलना diff
(जिसके लिए दो फ़ाइलों की आवश्यकता है, और इस मामले में हम इसे दो फ़ाइल डिस्क्रिप्टर दे रहे हैं)
diff <(ls /bin) <(ls /usr/bin)
< <
उपयोग किया जाता है जब एक प्रक्रिया प्रतिस्थापन से एक स्टड हो रही है । ऐसा आदेश लग सकता है cmd1 < <(cmd2)
:। उदाहरण के लिए,wc < <(date)
< <
खुद के द्वारा एक चीज नहीं है, प्रक्रिया प्रतिस्थापन के मामले में यह सिर्फ एक <
और चीज है जो इसके साथ शुरू होती है<
<<<
पहले इसे 9 आर खोल के यूनिक्स बंदरगाह द्वारा लागू किया गया था , बाद में इसे zsh, bash और ksh93 द्वारा अपनाया गया। मैं तब इसे बशीवाद नहीं कहूंगा।
echo 'foo' | read; echo ${REPLY}
जाएगा नहीं लौटने foo
, क्योंकि read
एक उप खोल में शुरू कर दिया है - पाइपिंग एक उप खोल शुरू होता है। हालांकि, read < <(echo 'foo'); echo ${REPLY}
सही ढंग से रिटर्न foo
, क्योंकि कोई उप-शेल नहीं है।
< <
एक वाक्यविन्यास त्रुटि है:
$ cat < <
bash: syntax error near unexpected token `<'
< <()
है प्रक्रिया प्रतिस्थापन ( <()
) (पुनर्निर्देशन के साथ संयुक्त <
):
एक आकस्मिक उदाहरण:
$ wc -l < <(grep ntfs /etc/fstab)
4
$ wc -l <(grep ntfs /etc/fstab)
4 /dev/fd/63
प्रक्रिया प्रतिस्थापन के साथ, फ़ाइल डिस्क्रिप्टर का मार्ग फ़ाइल नाम की तरह उपयोग किया जाता है। यदि आप सीधे फ़ाइल नाम का उपयोग नहीं करना चाहते (या नहीं कर सकते हैं), तो आप प्रक्रिया प्रतिस्थापन को पुनर्निर्देशन के साथ जोड़ देते हैं।
स्पष्ट होने के लिए, कोई < <
ऑपरेटर नहीं है।
<()
एक फ़ाइल नाम की तरह बात कर देता है, तो यह अधिक आम तौर पर उपयोगी है - < <()
stdin जहां यह आवश्यक नहीं हो सकता है की जगह है। में wc
, उत्तरार्द्ध अधिक उपयोगी होता है। यह कहीं और कम उपयोगी हो सकता है
< <
एक सिंटैक्स त्रुटि है, आप शायद मतलब है command1 < <( command2 )
जो एक सरल इनपुट पुनर्निर्देशन एक प्रक्रिया प्रतिस्थापन के बाद है और बहुत समान है, लेकिन इसके बराबर नहीं है:
command2 | command1
आपके द्वारा चलाए bash
जा रहे अंतर command1
को दूसरे मामले में एक उपधारा में चलाया जाता है, जबकि यह पहले वाले में वर्तमान शेल में चलाया जाता है। इसका मतलब है कि सेट किए गए वैरिएबल command1
प्रक्रिया प्रतिस्थापन संस्करण के साथ खो नहीं जाएंगे।
< <
एक सिंटैक्स त्रुटि देगा। उचित उपयोग निम्नानुसार है:
उदाहरणों की मदद से समझाते हुए:
इसके लिए उदाहरण < <()
:
while read line;do
echo $line
done< <(ls)
उपरोक्त उदाहरण में, जबकि लूप का इनपुट ls
कमांड से आएगा जिसे echo
लूप में लाइन और एड द्वारा लाइन पढ़ा जा सकता है ।
<()
प्रक्रिया प्रतिस्थापन के लिए प्रयोग किया जाता है। अधिक जानकारी और उदाहरण के लिए <()
इस लिंक पर पाया जा सकता है: