Q1। क्षेत्र विभाजन।
क्या क्षेत्र विभाजन शब्द विभाजन के समान है?
हां, दोनों एक ही विचार की ओर इशारा करते हैं।
क्या IFS=''अशक्त के रूप में एक ही सेटिंग है, एक खाली स्ट्रिंग के समान है?
हां, तीनों का अर्थ समान है: कोई क्षेत्र / शब्द विभाजन नहीं किया जाएगा। इसके अलावा, यह मुद्रण क्षेत्रों को प्रभावित करता है (जैसा कि echo "$*") सभी क्षेत्रों को बिना किसी स्थान के साथ एक साथ समतल किया जाएगा।
Q3: (एक भाग) परेशान IFS।
POSIX विनिर्देश में, मैंने निम्नलिखित पढ़ा :
यदि IFS सेट नहीं है, तो शेल ऐसा व्यवहार करेगा जैसे कि IFS का मान <space> <tab> <newline> है ।
जो बिल्कुल इसके बराबर है:
ए के साथ unset IFS, शेल ऐसा व्यवहार करेगा जैसे आईएफएस डिफ़ॉल्ट है।
इसका मतलब है कि 'फ़ील्ड विभाजन' एक डिफ़ॉल्ट IFS मान के साथ ठीक वैसा ही होगा, या परेशान नहीं होगा।
इसका मतलब यह नहीं है कि IFS सभी परिस्थितियों में उसी तरह काम करेगा। अधिक विशिष्ट होने के नाते, को क्रियान्वित करने OldIFS=$IFSवर सेट हो जाएगा OldIFSकरने के लिए शून्य , डिफ़ॉल्ट नहीं। और IFS को वापस सेट करने की कोशिश कर रहा है, क्योंकि यह IFS=OldIFSIFS को अशक्त करने के लिए सेट करेगा, इसे अप्रसन्न न रखें जैसा कि पहले था। ध्यान रहे !!।
Q3: (भाग b) IFS को पुनर्स्थापित करें।
मैं डिफ़ॉल्ट रूप से IFS का मान कैसे पुनर्स्थापित कर सकता हूं। मान लें कि मैं IFS के डिफ़ॉल्ट मान को पुनर्स्थापित करना चाहता हूं। मैं उसको कैसे करू? (अधिक विशेष रूप से, मैं <टैब> और <newline> का संदर्भ कैसे दूं ?]
Zsh, ksh और bash (AFAIK) के लिए, IFS को डिफ़ॉल्ट मान पर सेट किया जा सकता है:
IFS=$' \t\n' # works with zsh, ksh, bash.
हो गया, आपको और कुछ नहीं पढ़ना चाहिए।
लेकिन अगर आपको sh के लिए IFS को फिर से सेट करना है, तो यह जटिल हो सकता है।
चलो कमियों (जटिलता को छोड़कर) के साथ आसानी से पूरा करने के लिए एक नज़र डालें।
1.- परेशान IFS।
हम बस unset IFS(पढ़ें Q3 हिस्सा एक, ऊपर)।
2.- स्वैप चार्ट।
वर्कअराउंड के रूप में, टैब और न्यूलाइन के मान को स्वैप करने से IFS का मान सेट करना आसान हो जाता है, और फिर यह बराबर तरीके से काम करता है।
IFS को <space> <newline> <tab> पर सेट करें :
sh -c 'IFS=$(echo " \n\t"); printf "%s" "$IFS"|xxd' # Works.
3.- एक साधारण? उपाय:
अगर ऐसी बाल स्क्रिप्ट हैं, जिन्हें सही ढंग से IFS की आवश्यकता है, तो आप हमेशा स्वयं लिख सकते हैं:
आईएफएस = '
'
जहां अनुक्रम मैन्युअल रूप से टाइप किया गया था: IFS='spacetabnewline'अनुक्रम, जो वास्तव में सही ढंग से ऊपर टाइप किया गया है (यदि आपको पुष्टि करने की आवश्यकता है, तो इस उत्तर को संपादित करें)। लेकिन आपके ब्राउज़र से एक कॉपी / पेस्ट टूट जाएगा क्योंकि ब्राउज़र व्हाट्सएप को निचोड़ / छिपा देगा। ऊपर लिखे अनुसार कोड को साझा करना मुश्किल हो जाता है।
4.- पूरा समाधान।
कोड लिखने के लिए जिसे सुरक्षित रूप से कॉपी किया जा सकता है, उसमें आमतौर पर अस्पष्ट प्रिंट करने योग्य भाग शामिल होते हैं।
हमें कुछ कोड की आवश्यकता है जो अपेक्षित मूल्य का "उत्पादन" करते हैं। लेकिन, भले ही वैचारिक रूप से सही हो, यह कोड एक अनुगामी निर्धारित नहीं करेगा \n:
sh -c 'IFS=$(echo " \t\n"); printf "%s" "$IFS"|xxd' # wrong.
ऐसा इसलिए होता है, क्योंकि अधिकांश गोले के तहत, विस्तार पर कमांड $(...)या `...`कमांड प्रतिस्थापन की सभी नई रूपरेखाएँ हटा दी जाती हैं।
हमें श के लिए एक ट्रिक का उपयोग करने की आवश्यकता है :
sh -c 'IFS="$(printf " \t\nx")"; IFS="${IFS%x}"; printf "$IFS"|xxd' # Correct.
एक वैकल्पिक तरीका हो सकता है कि IFS को बैश (उदाहरण के लिए) से पर्यावरण के मान के रूप में सेट करें और फिर sh (इसके संस्करण जो IFS को पर्यावरण के माध्यम से सेट होने के लिए स्वीकार करते हैं), इस प्रकार:
env IFS=$' \t\n' sh -c 'printf "%s" "$IFS"|xxd'
संक्षेप में, श काफी अजीब रोमांच को डिफ़ॉल्ट करने के लिए IFS को रीसेट करता है।
Q4: वास्तविक कोड में:
अंत में, यह कोड कैसे होगा:
while IFS= read -r line
do
echo $line
done < /path_to_text_file
व्यवहार करें कि क्या हम पहली पंक्ति को बदलते हैं
while read -r line # Use the default IFS value
या इसमें:
while IFS=' ' read -r line
पहला: मैं नहीं जानता कि क्या echo $line(var नहीं उद्धृत के साथ) वहाँ पर है, या नहीं। यह 'फ़ील्ड विभाजन' के एक दूसरे स्तर का परिचय देता है जो कि पढ़ने के लिए नहीं है। तो मैं दोनों को जवाब दूंगा। :)
इस कोड के साथ (ताकि आप पुष्टि कर सकें)। आपको उपयोगी xxd की आवश्यकता होगी :
#!/bin/ksh
# Correctly set IFS as described above.
defIFS="$(printf " \t\nx")"; defIFS="${defIFS%x}";
IFS="$defIFS"
printf "IFS value: "
printf "%s" "$IFS"| xxd -p
a=' bar baz quz '; l="${#a}"
printf "var value : %${l}s-" "$a" ; printf "%s\n" "$a" | xxd -p
printf "%s\n" "$a" | while IFS='x' read -r line; do
printf "IFS --x-- : %${l}s-" "$line" ;
printf "%s" "$line" |xxd -p; done;
printf 'Values quoted :\n' "" # With values quoted:
printf "%s\n" "$a" | while IFS='' read -r line; do
printf "IFS null quoted : %${l}s-" "$line" ;
printf "%s" "$line" |xxd -p; done;
printf "%s\n" "$a" | while IFS="$defIFS" read -r line; do
printf "IFS default quoted : %${l}s-" "$line" ;
printf "%s" "$line" |xxd -p; done;
unset IFS; printf "%s\n" "$a" | while read -r line; do
printf "IFS unset quoted : %${l}s-" "$line" ;
printf "%s" "$line" |xxd -p; done;
IFS="$defIFS" # set IFS back to default.
printf "%s\n" "$a" | while IFS=' ' read -r line; do
printf "IFS space quoted : %${l}s-" "$line" ;
printf "%s" "$line" |xxd -p; done;
printf '%s\n' "Values unquoted :" # Now with values unquoted:
printf "%s\n" "$a" | while IFS='x' read -r line; do
printf "IFS --x-- unquoted : "
printf "%s, " $line; printf "%s," $line |xxd -p; done
printf "%s\n" "$a" | while IFS='' read -r line; do
printf "IFS null unquoted : ";
printf "%s, " $line; printf "%s," $line |xxd -p; done
printf "%s\n" "$a" | while IFS="$defIFS" read -r line; do
printf "IFS defau unquoted : ";
printf "%s, " $line; printf "%s," $line |xxd -p; done
unset IFS; printf "%s\n" "$a" | while read -r line; do
printf "IFS unset unquoted : ";
printf "%s, " $line; printf "%s," $line |xxd -p; done
IFS="$defIFS" # set IFS back to default.
printf "%s\n" "$a" | while IFS=' ' read -r line; do
printf "IFS space unquoted : ";
printf "%s, " $line; printf "%s," $line |xxd -p; done
मुझे मिला:
$ ./stackexchange-Understanding-IFS.sh
IFS value: 20090a
var value : bar baz quz -20202062617220202062617a20202071757a2020200a
IFS --x-- : bar baz quz -20202062617220202062617a20202071757a202020
Values quoted :
IFS null quoted : bar baz quz -20202062617220202062617a20202071757a202020
IFS default quoted : bar baz quz-62617220202062617a20202071757a
IFS unset quoted : bar baz quz-62617220202062617a20202071757a
IFS space quoted : bar baz quz-62617220202062617a20202071757a
Values unquoted :
IFS --x-- unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
IFS null unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
IFS defau unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
IFS unset unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
IFS space unquoted : bar, baz, quz, 6261722c62617a2c71757a2c
पहला मान सिर्फ सही मूल्य है IFS='spacetabnewline'
अगली पंक्ति सभी हेक्स मान है जो कि var $aमें है, और अंत में एक नई लाइन '0a' है क्योंकि यह प्रत्येक रीड कमांड को दिया जाने वाला है।
अगली पंक्ति, जिसके लिए IFS शून्य है, कोई 'फ़ील्ड विभाजन' नहीं करता है, लेकिन नई पंक्ति को हटा दिया जाता है (जैसा कि अपेक्षित है)।
अगली तीन पंक्तियाँ, क्योंकि IFS में एक स्थान होता है, प्रारंभिक रिक्त स्थान को हटा दें और शेष शेष के लिए var पंक्ति सेट करें।
अंतिम चार पंक्तियों से पता चलता है कि एक अछूता चर क्या करेगा। मानों को (कई) रिक्त स्थान पर विभाजित किया जाएगा और इसे निम्नानुसार मुद्रित किया जाएगा:bar,baz,qux,
IFSऔर एक परेशानIFSबहुत अलग है। Q4 का उत्तर आंशिक रूप से गलत है: आंतरिक विभाजकों को यहां स्पर्श नहीं किया जाता है, केवल प्रमुख और अनुगामी होते हैं।