बैश "IFS" चर के मूल्य के आधार पर अपने व्यवहार को बदलता है


18

जब मैं IFSचर को एक स्थान पर सेट करता हूं , तो bashकई स्थानों को एक स्थान के रूप में मानता है ( myprogramयह एक प्रोग्राम है जो कमांड लाइन तर्कों को प्राप्त करता है):

IFS=" "
x="hello   hi   world"
./myprogram $x
argv[1] = hello
argv[2] = hi
argv[3] = world

लेकिन जब मैं IFSएक अल्पविराम के लिए चर सेट करता हूं , bashतो कई अल्पविरामों को एक अल्पविराम के रूप में नहीं मानता है:

IFS=","
x="hello,,,hi,,,world"
./myprogram $x
argv[1] = hello
argv[2] = 
argv[3] = 
argv[4] = hi
argv[5] = 
argv[6] = 
argv[7] = world

ऐसा क्यों है?


बस संदर्भ के लिए, "IFS" का अर्थ है आंतरिक क्षेत्र विभाजक
13:12 पर pr1268

जवाबों:


21

इसमें प्रलेखित है man bash। आईएफएस में किसी भी चरित्र की एक एकल घटना जो व्हाट्सएप नहीं है एक क्षेत्र का परिसीमन करती है।

से man bash:

शेल आईएफएस के प्रत्येक चरित्र को एक सीमांकक के रूप में मानता है, और अन्य वर्णों के परिणामों को इन शब्दों को फ़ील्ड टर्मिनेटर के रूप में उपयोग करके विभाजित करता है। अगर भारतीय विदेश सेवा सेट नहीं है, या अपने मूल्य ठीक है <space><tab><newline>, डिफ़ॉल्ट, तो के दृश्यों <space>, <tab>और <newline>शुरुआत और पिछले विस्तार के परिणामों के अंत में ध्यान नहीं दिया जाता है, और शुरुआत में या अंत नहीं आईएफएस वर्णों के किसी अनुक्रम परिसीमित करने के लिए कार्य करता है शब्दों। यदि IFS का डिफ़ॉल्ट के अलावा कोई मान है, तो शब्द के आरंभ और अंत में व्हॉट्सएप वर्णों के स्थान, टैब और न्यूलाइन को नजरअंदाज कर दिया जाता है, जब तक कि व्हॉट्सएप वर्ण IFS (IFS व्हॉट्सएप वर्ण) के मान में है )। IFS में कोई भी वर्ण IFS व्हाट्सएप नहीं है, साथ ही किसी भी आसन्न IFS व्हाट्सएप वर्ण के साथ, एक क्षेत्र का परिसीमन करता है। IFS व्हॉट्सएप पात्रों का एक अनुक्रम भी एक सीमांकक के रूप में माना जाता है। यदि IFS का मान शून्य है, तो कोई शब्द विभाजन नहीं होता है। [महत्व दिया।]

उदाहरण: क्षेत्र विभाजन

यदि IFS में कोई व्हाट्सएप वर्ण नहीं है, तो व्हाट्सएप को खेतों में शामिल किया जाता है:

$ ( IFS=',' x='one , two,three'; printf "<%s>\n" $x )
<one >
< two>
<three>

यदि IFS के पास खाली और अल्पविराम दोनों होते हैं, तो कम्बल के अनुक्रम, उसके बाद अल्पविराम के बाद, रिक्त स्थान के अनुक्रमों को एक एकल सीमांकक के रूप में माना जाता है:

$ ( IFS=' ,' x='one , two,three'; printf "<%s>\n" $x )
<one>
<two>
<three>

अल्पविरामों के अनुक्रम को खाली क्षेत्रों के अनुक्रम के रूप में व्याख्या की जाती है:

$ ( IFS=' ,' x='one,,,two,three'; printf "<%s>\n" $x )
<one>
<>
<>
<two>
<three>

उदाहरण: व्हाट्सएप का प्रमुख और अनुगामी होना

यदि IFS में कोई व्हाट्सएप नहीं है, तो किसी भी अग्रणी और अनुगामी व्हाट्सएप को खेतों में रखा जाता है:

$ ( IFS=',' x='  one , two,three  ,'; printf "<%s>\n" $x )
<  one >
< two>
<three  >

यदि IFS में रिक्त स्थान होते हैं, तो रिक्त स्थान के किसी भी अग्रणी या अनुगामी अनुक्रम को हटा दिया जाता है:

$ ( IFS=' ,' x='  one , two,three  ,'; printf "<%s>\n" $x )
<one>
<two>
<three>

हो सकता है "व्हाट्सएप कैरेक्टर स्पेस, टैब और न्यूलाइन के सिक्वेंस पर जोर दिया जाए, जब तक शब्द की शुरुआत और अंत में व्हाट्सएप कैरेक्टर को नजरअंदाज कर दिया जाए, जब तक कि व्हॉट्सएप कैरेक्टर IFS की वैल्यू में न हो जाए"
Jeff Schaller

@JeffSchaller उत्कृष्ट विचार: मैंने अभी उस पर एक खंड जोड़ा है।
जॉन १०२४२४ ३०'१


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

@Davos एक टैब द्वारा सीमांकित प्रत्येक फ़ील्ड के डेटा के लिए, अन्य टूल का उपयोग करना अधिक स्वाभाविक हो सकता है जो इसे आसानी से संभालते हैं जैसे awkकि -F'\t'विकल्प के साथ या cut। वैकल्पिक रूप से, यदि आपके पास हाल का संस्करण है bash, तो आप विकल्प के readarrayसाथ फ़ील्ड का उपयोग करने में सक्षम हो सकते हैं -d$'\t'
जॉन 1024
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.