मैं क्षेत्र विभाजन के लिए एक अस्थायी IFS का उपयोग कब कर सकता हूं?


19

बैश में, कहते हैं कि आपके पास है var=a.b.c.:

$ IFS=. printf "%s\n" $var
a.b.c

हालाँकि, IFSसरणी बनाते समय इस तरह का उपयोग प्रभावी होता है:

$ IFS=. arr=($var)
$ printf "%s\n" "${arr[@]}"
a
b
c

यह बहुत सुविधाजनक है, निश्चित है, लेकिन यह कहां से प्रलेखित है? बैश डॉक्यूमेंटेशन में एरेस या वर्ड स्प्लिटिंग पर सेक्शन का त्वरित पठन किसी भी तरह से कोई संकेत नहीं देता है। एकल-पृष्ठ दस्तावेज़ केIFS माध्यम से खोज इस आशय के बारे में कोई संकेत नहीं देती है।

मुझे यकीन नहीं है कि जब मैं मज़बूती से कर सकता हूँ:

IFS=x do something

और उम्मीद है कि IFSक्षेत्र विभाजन को प्रभावित करेगा।

जवाबों:


28

मूल विचार यह है कि VAR=VALUE some-commandसेट VARकरने के लिए VALUEके निष्पादन के लिए some-commandजब some-commandएक बाहरी आदेश है, और यह है कि अधिक से अधिक कल्पना नहीं मिलता है। यदि आप इस अंतर्ज्ञान को कुछ ज्ञान के साथ जोड़ते हैं कि शेल कैसे काम करता है, तो आपको ज्यादातर मामलों में सही उत्तर के साथ आना चाहिए। POSIX संदर्भ "शेल कमांड लैंग्वेज" अध्याय में "साधारण कमांड" है

यदि some-commandएक बाहरी कमांड है , VAR=VALUE some-commandके बराबर है env VAR=VALUE some-commandVARके वातावरण में निर्यात किया जाता है some-command, और शेल में इसका मूल्य (या मूल्य की कमी) नहीं बदलता है।

यदि some-commandकोई फ़ंक्शन है , तो VAR=VALUE some-commandसमतुल्य है VAR=VALUE; some-command, अर्थात फ़ंक्शन के वापस आने के बाद असाइनमेंट बना रहता है , और चर को पर्यावरण में निर्यात नहीं किया जाता है। इसका कारण बॉर्न शेल के डिजाइन के साथ करना है (और बाद में अनुकूलता के साथ): इसमें फ़ंक्शन के निष्पादन के आसपास चर मानों को सहेजने और पुनर्स्थापित करने की कोई सुविधा नहीं थी। शेल में एक्सपोर्ट नहीं करने से कोई मतलब नहीं है क्योंकि शेल में ही कोई फंक्शन निष्पादित होता है। हालाँकि, ksh (ATT ksh93 और pdksh / mksh दोनों सहित), bash और zsh अधिक उपयोगी व्यवहार को लागू करते हैं जहां VARकेवल फ़ंक्शन के निष्पादन के दौरान सेट किया जाता है (यह भी निर्यात किया जाता है)। में ksh , इस करता है, तो समारोह ksh वाक्य रचना के साथ परिभाषित किया गया है किया जाता हैfunction NAME …, अगर यह मानक वाक्यविन्यास के साथ परिभाषित नहीं है NAME ()। में bash , यह केवल बैश मोड में किया जाता है, POSIX मोड में नहीं है (जब साथ चलाने POSIXLY_CORRECT=1)। में zsh , इस करता है, तो किया जाता है posix_builtinsविकल्प सेट नहीं है; यह विकल्प डिफ़ॉल्ट रूप से सेट नहीं है, लेकिन इसके द्वारा चालू है emulate shया emulate ksh

यदि some-commandएक बिलिन है, तो व्यवहार बिलिन के प्रकार पर निर्भर करता है। विशेष बिल्डिंस कार्यों की तरह व्यवहार करते हैं। विशेष अंतर्निहित इन्स शेल के अंदर लागू किए जाने वाले हैं क्योंकि वे राज्य शेल को प्रभावित करते हैं (जैसे breakनियंत्रण प्रवाह को cdप्रभावित करता है, वर्तमान निर्देशिका को setप्रभावित करता है , स्थितिगत मापदंडों और विकल्पों को प्रभावित करता है ...)। अन्य बिलिन केवल प्रदर्शन और सुविधा के लिए निर्मित होते हैं (ज्यादातर - जैसे बैश फीचर printf -vकेवल एक बिलिन द्वारा लागू किया जा सकता है), और वे एक बाहरी कमांड की तरह व्यवहार करते हैं।

अलियास विस्तार के बाद असाइनमेंट होता है, इसलिए यदि some-commandकोई अन्य नाम है , तो यह पता लगाने के लिए कि क्या होता है, इसे पहले विस्तारित करें।

ध्यान दें कि सभी मामलों में, कमांड लाइन को पार्स करने के बाद असाइनमेंट किया जाता है, जिसमें कमांड लाइन पर कोई भी वैरिएबल प्रतिस्थापन शामिल है। तो var=a; var=b echo $varप्रिंट करता है a, क्योंकि $varअसाइनमेंट होने से पहले मूल्यांकन किया जाता है। और इस प्रकार विभाजित करने के IFS=. printf "%s\n" $varलिए पुराने IFSमूल्य का उपयोग करता है $var

मैंने सभी प्रकार के आदेशों को कवर कर लिया है, लेकिन एक और मामला है: जब निष्पादित करने के लिए कोई कमांड नहीं है , अर्थात यदि कमांड में केवल असाइनमेंट (और संभवतः पुनर्निर्देशन) शामिल हैं। उस स्थिति में, असाइनमेंट यथावत रहता हैVAR=VALUE OTHERVAR=OTHERVALUEके बराबर है VAR=VALUE; OTHERVAR=OTHERVALUE। इसके बाद IFS=. arr=($var), IFSसेट पर रहता है .। चूंकि आप $IFSअसाइनमेंट में arrइस उम्मीद के साथ उपयोग कर सकते हैं कि पहले से ही इसका नया मूल्य है, इसलिए यह समझ में आता है कि नए मूल्य का IFSउपयोग विस्तार के लिए किया जाता है $var

सारांश में, आप केवल अस्थायी क्षेत्र विभाजन के IFSलिए उपयोग कर सकते हैं :

  • एक नया शेल या एक उपधारा शुरू करके (जैसे third=$(IFS=.; set -f; set -- $var; echo "$3")कि यह करने का एक जटिल तरीका है third=${var#*.*.}कि वे अलग व्यवहार करते हैं जब varदो .वर्णों से कम का मान होता है );
  • ksh में, IFS=. some-functionजहाँ some-functionksh वाक्य रचना के साथ परिभाषित किया गया है function some-function …;
  • बैश और zsh में, IFS=. some-functionजब तक वे संगतता मोड के विपरीत देशी मोड में काम कर रहे हैं।

" ईक" पर IFSसेट रहता है .। पहला भाग पढ़ने के बाद, यह समझ में आता है, लेकिन इससे पहले कि मैं इस क्यू को पोस्ट करूँ, मुझे उम्मीद नहीं होगी।
मूरू

1
यह एक अलग प्रश्न का उत्तर है
schily

कुछ साल पहले के इस उत्तर में कुछ अतिरिक्त व्याख्या ।
Ti Strga

6

@ गिल्स का जवाब वास्तव में बहुत अच्छा है, वह एक जटिल मुद्दे पर (विस्तार से) बताते हैं।

हालांकि, मेरा मानना ​​है कि इस आदेश का जवाब क्यों:

$ IFS=. printf "%s\n" $var
a.b.c

काम करता है के रूप में यह सरल विचार है कि पूरी कमांड लाइन निष्पादित होने से पहले पार्स है। और यह कि प्रत्येक "शब्द" एक बार शेल द्वारा संसाधित होता है। कार्य, जैसे , विलंब हुआ है (चरण 4 पिछले एक है):
IFS=.

4.- प्रत्येक चर असाइनमेंट का विस्तार किया जाएगा ...

कमांड निष्पादित होने से ठीक पहले तक और तर्कों में सभी विस्तारकों को इस निष्पादन योग्य लाइन के निर्माण के लिए पहले संसाधित किया जाता है:

$ IFS=. printf "%s\n" a.b.c           ## IFS=. goes to the environment.
a.b.c

के मान $varको "पुराने" भारतीय विदेश सेवा के साथ विस्तार किया जाता है a.b.cआदेश से पहले printfतर्क दिया जाता है "%s\n"और a.b.c

eval

विलंब का एक स्तर निम्नलिखित द्वारा पेश किया जा सकता है eval:

$ IFS=. eval printf "'%s\n'" \$var
a
b
c

लाइन को पार्स (पहली बार) और 'IFS =' किया गया है। इस रूप में पर्यावरण के लिए सेट है:

$ printf '%s\n' $var

फिर इसे इसके लिए फिर से पार्स किया जाता है:

$ printf '%s\n' a b c

और इस पर अमल किया:

a
b
c

का मूल्य $var(एबीसी) उपयोग में भारतीय विदेश सेवा के मूल्य के साथ विभाजित है: .

वातावरण

जटिल और मुश्किल हिस्सा वह है जो पर्यावरण में मान्य है जब !!!

गाइल्स उत्तर के पहले भाग में इसे बहुत अच्छी तरह से समझाया गया है।

एक अतिरिक्त विवरण के साथ।

जब यह आदेश निष्पादित किया जाता है:

$ IFS=. arr=($var)

IFS का मान वर्तमान परिवेश में बरकरार है, हां:

$ printf '<%s>  ' "${arr[@]}" "$IFS"
<a>  <b>  <c>  <.> 

एक कथन के लिए IFS।

लेकिन इसे टाला जा सकता था: एक कथन के लिए IFS की स्थापना

$ IFS=. command eval arr\=\(\$var\)

$  printf '<%s>  ' "${arr[@]}" "$IFS"
<a>  <b>  <c>  < 
> 

2

आपके प्रश्न के बारे में

var=a.b.c
IFS=. printf "%s\n" $var

एक कोने का मामला है।

ऐसा इसलिए है क्योंकि शेल चर सेट macro expansionहोने से पहले कमांड में होता IFS=.है।

दूसरे शब्दों में: जब $varविस्तार किया जाता है, तो पिछला IFSमान सक्रिय होता है, फिर IFSसेट किया जाता है '.'

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