जवाबों:
आप प्रक्रिया प्रतिस्थापन के साथ थोड़ी देर के लूप का उपयोग कर सकते हैं:
while read -r line
do
echo "$line"
done < <(jobs)
मल्टीलाइन चर को पढ़ने का एक इष्टतम तरीका एक रिक्त IFS
चर और printf
परिवर्तनशील नई रेखा के साथ चर को सेट करना है :
# Printf '%s\n' "$var" is necessary because printf '%s' "$var" on a
# variable that doesn't end with a newline then the while loop will
# completely miss the last line of the variable.
while IFS= read -r line
do
echo "$line"
done < <(printf '%s\n' "$var")
नोट: शेलचेक sc2031 के अनुसार, सबस्टेशन बनाने से बचने के लिए प्रक्रिया सबस्टेशन का उपयोग पाइप के लिए बेहतर है।
इसके अलावा, कृपया महसूस करें कि चर का नामकरण करने jobs
से भ्रम पैदा हो सकता है क्योंकि यह एक सामान्य शेल कमांड का नाम भी है।
echo
है printf %s
, ताकि आपकी स्क्रिप्ट नॉन-टैम इनपुट के साथ भी काम करे।
/tmp
निर्देशिका को लिखने योग्य बनाने की आवश्यकता होती है , क्योंकि यह एक अस्थायी कार्य फ़ाइल बनाने में सक्षम होने पर निर्भर करता है। क्या आपको कभी भी खुद को /tmp
केवल पढ़ने के लिए एक प्रतिबंधित प्रणाली पर खोजना चाहिए (और आपके द्वारा परिवर्तनशील नहीं), आप वैकल्पिक समाधान का उपयोग करने की संभावना के बारे में खुश होंगे, जैसे कि printf
पाइप के साथ ।
printf "%s\n" "$var" | while IFS= read -r line
लाइन ( स्पष्टीकरण ) द्वारा कमांड लाइन के आउटपुट को संसाधित करने के लिए :
jobs |
while IFS= read -r line; do
process "$line"
done
यदि आपके पास पहले से ही एक चर में डेटा है:
printf %s "$foo" | …
printf %s "$foo"
लगभग समान है echo "$foo"
, लेकिन $foo
शाब्दिक रूप से प्रिंट करता है, जबकि गूंज कमांड के विकल्प के रूप में echo "$foo"
व्याख्या कर सकता है $foo
यदि यह एक के साथ शुरू होता है -
, और $foo
कुछ गोले में बैकलैश अनुक्रम का विस्तार कर सकता है ।
ध्यान दें कि कुछ गोले में (ऐश, बाश, पीडीएस, लेकिन केश या ज़श नहीं), पाइप लाइन का दाहिना हाथ एक अलग प्रक्रिया में चलता है, इसलिए लूप में आपके द्वारा सेट किया गया कोई भी चर खो जाता है। उदाहरण के लिए, निम्न पंक्ति-गणना स्क्रिप्ट इन शेल में 0 प्रिंट करता है:
n=0
printf %s "$foo" |
while IFS= read -r line; do
n=$(($n + 1))
done
echo $n
एक $n
आदेश सूची में शेष स्क्रिप्ट (या कम से कम उस भाग की आवश्यकता होती है जिसे लूप से मूल्य की आवश्यकता होती है ) डालते हैं :
n=0
printf %s "$foo" | {
while IFS= read -r line; do
n=$(($n + 1))
done
echo $n
}
यदि गैर-खाली लाइनों पर अभिनय करना काफी अच्छा है और इनपुट बहुत बड़ा नहीं है, तो आप शब्द विभाजन का उपयोग कर सकते हैं:
IFS='
'
set -f
for line in $(jobs); do
# process line
done
set +f
unset IFS
स्पष्टीकरण: IFS
एक ही नई पंक्ति पर सेट करने से शब्द विभाजन के रूप में नई सीमा पर ही होता है (डिफ़ॉल्ट सेटिंग के तहत किसी भी व्हाट्सएप चरित्र के विपरीत)। set -f
ग्लोबिंग (यानी वाइल्डकार्ड विस्तार) को बंद कर देता है, जो अन्यथा कमांड प्रतिस्थापन $(jobs)
या एक चर सबस्टीट्यूटिनो के परिणाम के रूप में होता है $foo
। for
लूप के सभी टुकड़ों पर काम करता है $(jobs)
, जो सभी आदेश उत्पादन में गैर खाली लाइनें हैं। अंत में, ग्लोबिंग और IFS
सेटिंग्स को पुनर्स्थापित करें ।
local IFS=something
। यह वैश्विक-गुंजाइश मूल्य को प्रभावित नहीं करेगा। IIRC, unset IFS
आपको डिफ़ॉल्ट पर वापस नहीं लाता है (और निश्चित रूप से यह काम नहीं करता है अगर यह पहले से डिफ़ॉल्ट नहीं था)।
समस्या: यदि आप लूप का उपयोग करते हैं तो यह सब-सब में चलेगा और सभी चर खो जाएंगे। समाधान: लूप के लिए उपयोग करें
# change delimiter (IFS) to new line.
IFS_BAK=$IFS
IFS=$'\n'
for line in $variableWithSeveralLines; do
echo "$line"
# return IFS back if you need to split new line by spaces:
IFS=$IFS_BAK
IFS_BAK=
lineConvertedToArraySplittedBySpaces=( $line )
echo "{lineConvertedToArraySplittedBySpaces[0]}"
# return IFS back to newline for "for" loop
IFS_BAK=$IFS
IFS=$'\n'
done
# return delimiter to previous value
IFS=$IFS_BAK
IFS_BAK=
while read
बैश में एक लूप में पाइपिंग का मतलब है जबकि लूप एक सब-उप में है, इसलिए चर वैश्विक नहीं हैं। while read;do ;done <<< "$var"
लूप बॉडी को एक सबशेल नहीं बनाता है। (हाल के बैश में cmd | while
लूप के शरीर को एक उप-भाग में नहीं रखने का विकल्प होता है , जैसे ksh में हमेशा होता है।)
हाल के बैश संस्करणों में, कमांड आउटपुट को सरणियों में कुशलतापूर्वक पढ़ने mapfile
या उपयोग readarray
करने के लिए
$ readarray test < <(ls -ltrR)
$ echo ${#test[@]}
6305
डिस्क्लेमर: भयानक उदाहरण, लेकिन आप अपने आप को एलएस की तुलना में उपयोग करने के लिए बेहतर आदेश दे सकते हैं
readarray
एक फ़ंक्शन में डालें और फ़ंक्शन को कुछ बार कॉल करें।
आप <<< का उपयोग केवल चर से पढ़े जाने वाले न्यूलाइन-सेपरेट डेटा से कर सकते हैं:
while read -r line
do
echo "A line of input: $line"
done <<<"$lines"
while IFS= read
read -r