`IFS = पढ़ते समय` में, IFS पर कोई प्रभाव क्यों नहीं पड़ता?


12

मैं कुछ बिलकुल ही गलत हो सकता है, लेकिन यह मेरे लिए समझाने लग रही है, में से एक के रूप में स्थापित करने के आईएफएस कि आदेशों में पूर्व कर / किया सूची बिल्कुल कोई प्रभाव नहीं है।
बाहरी IFS ( whileनिर्माण के बाहर ) नीचे दी गई स्क्रिप्ट में दिखाए गए सभी उदाहरणों में प्रबल है।

यहाँ क्या चल रहा है? क्या मुझे इस बात का गलत अंदाजा है कि इस स्थिति में IFS क्या करता है? मुझे उम्मीद थी कि सरणी-विभाजित परिणाम "अपेक्षित" कॉलम में दिखाए जाएंगे।


#!/bin/bash
xifs() { echo -n "$(echo -n "$IFS" | xxd -p)"; } # allow for null $IFS 
show() { x=($1) 
         echo -ne "  (${#x[@]})\t |"
         for ((j=0;j<${#x[@]};j++)); do 
           echo -n "${x[j]}|"
         done
         echo -ne "\t"
         xifs "$IFS"; echo
}
data="a  b   c"
echo -e "-----   --  -- \t --------\tactual"
echo -e "outside        \t  IFS    \tinside" 
echo -e "loop           \t Field   \tloop" 
echo -e "IFS     NR  NF \t Split   \tIFS (actual)" 
echo -e "-----   --  -- \t --------\t-----"
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while         read; do echo -ne '\t 1'; show "$REPLY"; done 
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS=    read; do echo -ne '\t 2'; show "$REPLY"; done 
IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS=b   read; do echo -ne '\t 3'; show "$REPLY"; done
IFS=" ";      xifs "$IFS"; echo "$data" | while         read; do echo -ne '\t 4'; show "$REPLY"; done 
IFS=" ";      xifs "$IFS"; echo "$data" | while IFS=    read; do echo -ne '\t 5'; show "$REPLY"; done 
IFS=" ";      xifs "$IFS"; echo "$data" | while IFS=b   read; do echo -ne '\t 6'; show "$REPLY"; done
IFS=;         xifs "$IFS"; echo "$data" | while         read; do echo -ne '\t 7'; show "$REPLY"; done 
IFS=;         xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne '\t 8'; show "$REPLY"; done 
IFS=;         xifs "$IFS"; echo "$data" | while IFS=b   read; do echo -ne '\t 9'; show "$REPLY"; done
IFS=b;        xifs "$IFS"; echo "$data" | while IFS=    read; do echo -ne '\t10'; show "$REPLY"; done
IFS=b;        xifs "$IFS"; echo "$data" | while IFS=" " read; do echo -ne '\t11'; show "$REPLY"; done
echo -e "-----   --  -- \t --------\t-----"

आउटपुट:

-----   --  --   --------       actual   
outside           IFS           inside                assigned   
loop             Field          loop    #              inner
IFS     NR  NF   Split          IFS     #  expected    IFS
-----   --  --   --------       -----   #  ---------  --------
20090a   1  (3)  |a|b|c|        20090a  #                              
20090a   2  (3)  |a|b|c|        20090a  #  |a  b   c|  IFS=
20090a   3  (3)  |a|b|c|        20090a  #  |a  |   c|  IFS=b
20       4  (3)  |a|b|c|        20      #                          
20       5  (3)  |a|b|c|        20      #  |a  b   c   IFS=
20       6  (3)  |a|b|c|        20      #  |a  |   c|  IFS=b
         7  (1)  |a  b   c|             #                          
         8  (1)  |a  b   c|             #  |a|b|c|     IFS=" "
         9  (1)  |a  b   c|             #  |a  |   c|  IFS=b
62      10  (2)  |a  |   c|     62      #  |a  b   c|  IFS=
62      11  (2)  |a  |   c|     62      #  |a|b|c|     IFS=" "
-----   --  --   --------       -----      ---------   -------                        

जवाबों:


17

(क्षमा करें, लंबी व्याख्या)

हां, IFSचर while IFS=" " read; do …का बाकी कोड पर कोई प्रभाव नहीं है।

आइए पहले सटीक रूप से बताएं कि शेल कमांड लाइन में दो अलग-अलग प्रकार के चर हैं:

  • शेल चर (जो केवल शेल के भीतर ही मौजूद हैं, और शेल के लिए स्थानीय हैं)
  • पर्यावरण चर, जो हर प्रक्रिया के लिए मौजूद हैं। वे आमतौर पर संरक्षित होते हैं fork()और exec()इसलिए बच्चे की प्रक्रिया उन्हें विरासत में मिलती है।

जब आप के साथ एक आदेश कहते हैं:

  A=foo B=bar command

कमांड को ऐसे वातावरण में क्रियान्वित किया जाता है जहां (पर्यावरण) चर Aसेट किया गया हो fooऔर Bजिसे सेट किया गया हो bar। लेकिन इस कमांड लाइन के साथ, वर्तमान शेल चर Aऔर अपरिवर्तितB रह जाते हैं ।

यह इससे अलग है:

A=foo; B=bar; command

यहां, शेल चर Aऔर Bपरिभाषित किए गए हैं और कमांड पर्यावरण चर Aऔर Bपरिभाषित के बिना चलाया जाता है । के मान Aऔर Bसे अस्वीकार्य हैं command

हालाँकि, यदि कुछ शेल वैरिएबल export-ed हैं, तो संबंधित परिवेश वैरिएबल उनके संबंधित शेल वैरिएबल के साथ सिंक्रनाइज़ किए जाते हैं। उदाहरण:

export A
export B
A=foo; B=bar; command

इस कोड के साथ, शेल चर और शेल पर्यावरण चर दोनों को सेट किया जाता है fooऔर bar। चूंकि पर्यावरण चर उप-प्रक्रियाओं द्वारा विरासत में मिले हैं, इसलिए commandवे अपने मूल्यों तक पहुंचने में सक्षम होंगे।

अपने मूल प्रश्न पर वापस जाने के लिए:

IFS='a' read

केवल readप्रभावित है। और वास्तव में, इस मामले में, चर readके मूल्य के बारे में परवाह नहीं है IFS। यह IFSतभी उपयोग करता है जब आप लाइन को विभाजित करने के लिए कहते हैं (और कई चर में संग्रहीत), जैसे:

echo "a :  b :    c" | IFS=":" read i j k; \
    printf "i is '%s', j is '%s', k is '%s'" "$i" "$j" "$k"

IFSreadजब तक इसे तर्कों के साथ नहीं बुलाया जाता है, तब तक इसका उपयोग नहीं किया जाता है। ( संपादित करें: यह बिल्कुल सच नहीं है: व्हॉट्सएप वर्ण, अर्थात स्थान और टैब, मौजूद IFSहैं जो हमेशा इनपुट लाइन की शुरुआत / अंत में अनदेखा किए जाते हैं।)


क्या शानदार व्याख्या है! यह इतना आसान है! मुझे महीनों से 'कोई अर्ध-बृहदान्त्र' सिंटैक्स नहीं मिला है; और यह बस इसका एक मामला है जिसका अर्थ है एक स्थानीय चर! .. rozcietrzewiacz ने दूसरे प्रश्न में मेरे (बड़े समय) के लिए मार्ग खोला ... और आपने बस केक पर टुकड़े डाल दिए हैं ... मैं कर रहा हूँ इस एक पर सारी रात, और यह निश्चित रूप से इस तरह के अच्छे और स्पष्ट उत्तरों के लिए लायक है! .. धन्यवाद ..
पीटर।

Uhm। मुझे उस टिप्पणी को कई बार पढ़ना पड़ा था, इससे पहले कि मैं मिल गया - आपके कहने का मतलब यह है कि व्हाट्सएप के जो पात्र मौजूद $IFSहैं, उन्हें इनपुट लाइन की शुरुआत / अंत में हटा दिया जाता है, मुझे लगता है? (जो है कि यह कैसे काम करता है।)
zrajm

कृपया इस पर एक नज़र डालें: unix.stackexchange.com/questions/382963/…

एकल चर को पढ़ते हुए भी IFS का मान महत्वपूर्ण है, क्योंकि शेल अभी भी इनपुट पर शब्द विभाजन करता है। उदाहरण के लिए, वर्णों a<tab>bको टाइप करने read varसे परिणामस्वरूप var का मान होगा a<space>b, लेकिन अगर आपके पास IFS='<newline>' read varइसके बाद भी var का मान होगा a<tab>b
जॉन हस्कल

8

इसे सरल रखें, आपकोIFS=<something> read ... अपने उदाहरण 1 में दिखाई देने वाले निर्माण के लिए एक समय में एक से अधिक चर को पढ़ना होगा

आप readउदाहरणों की गुंजाइश को याद करते हैं। आपके परीक्षण मामलों में लूप के अंदर IFS का कोई संशोधन नहीं है । मुझे बिल्कुल इंगित करने की अनुमति दें, जहां आपकी प्रत्येक पंक्ति में दूसरे IFS का प्रभाव पड़ता है:

 IFS=$' \t\n'; xifs "$IFS"; echo "$data" | while IFS=b   read; do echo ...
                                                      ^      ^
                                                      |      |
                                          from here --'       `- to here :)

यह शेल में निष्पादित किसी भी कार्यक्रम के साथ ही है। कमांड-लाइन पर आपके द्वारा (चर) परिभाषित चर कार्यक्रम के निष्पादन को प्रभावित करता है। और केवल वह (चूंकि आप निर्यात नहीं करते हैं)। इसलिए, IFSऐसी पंक्ति में पुनर्परिभाषित का उपयोग करने के लिए , आपको एक से अधिक चर केread लिए मान निर्दिष्ट करने के लिए कहना होगा । एक नज़र इन उदाहरणों पर है:

 $ data="a  b   c"
 $ echo "$data" | while           read A B C; do echo \|$A\|$B\|\|$C\|; done
 |a|b||c|
 $ echo "$data" | while IFS=      read A B C; do echo \|$A\|$B\|\|$C\|; done
 |a b c||||
 $ echo "$data" | while IFS='a'   read A B C; do echo \|$A\|$B\|\|$C\|; done
 || b c|||
 $ echo "$data" | while IFS='ab'  read A B C; do echo \|$A\|$B\|\|$C\|; done
 || || c|

1 जैसा कि मैंने अभी गिल्स से सीखा है , IFS=''केवल एक क्षेत्र को पढ़ते समय सेटिंग (रिक्त) का एक लाभ हो सकता है : यह लाइन की शुरुआत में व्हॉट्सएप के छंटनी से बचा जाता है।


अच्छा .. धन्यवाद ... मुझे यह समय मिल गया .. और मुझे आपका स्केच पसंद है :)
पीटर।

ठीक है, अब मैंने आपकी टिप्पणी पढ़ ली है, जिसे देख कर आपको उस प्रश्न में मेरे उत्तर पर ध्यान नहीं गया। हो सकता है कि आप बस दूसरे को वापस कर सकते हैं और इसे हटा सकते हैं, क्योंकि यह वास्तव में एक सामान्य मुद्दा है?
रोज़ज़ेट्राइजेविज़

हां, दो प्रश्नों में एक संबंधित विषय है, लेकिन दूसरे का शीर्षक " IFS= readIFS पर्यावरण चर को फिर से सेट करने के लिए वरीयता में क्यों उपयोग किया जाता है" है। मेरे पास जागरूकता नहीं थी, फिर भी, स्थानीय चर को कमांड के कॉलर द्वारा सेट किया जा सकता था। यही उस सवाल का जवाब था। यह इस प्रश्न के मुख्य बिंदु को संबोधित करने के लिए और अधिक विकसित हुआ, लेकिन जब तक मुझे एहसास हुआ कि, मैंने पहले ही यह प्रश्न पूछा था ... शायद दो प्रश्न दो प्रश्नों के समान हैं sed, इसलिए इसे रखने के लिए मेरी भावना ... Google को Google के लिए अधिक शीर्षक
पीटर।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.