जवाबों:
का प्रयोग करें cut
साथ _
क्षेत्र परिसीमक के रूप में और वांछित क्षेत्रों मिलती है:
A="$(cut -d'_' -f2 <<<'one_two_three_four_five')"
B="$(cut -d'_' -f4 <<<'one_two_three_four_five')"
आप echo
यहां स्ट्रिंग के बजाय उपयोग और पाइप कर सकते हैं :
A="$(echo 'one_two_three_four_five' | cut -d'_' -f2)"
B="$(echo 'one_two_three_four_five' | cut -d'_' -f4)"
उदाहरण:
$ s='one_two_three_four_five'
$ A="$(cut -d'_' -f2 <<<"$s")"
$ echo "$A"
two
$ B="$(cut -d'_' -f4 <<<"$s")"
$ echo "$B"
four
$ echo $FILE
my_user/my_folder/file.csv
$ A="$(cut -d'/' -f2 <<<"$FILE")"
$ echo $A
[file]*
क्या आप जानते हैं कि यहां क्या हो रहा है?
echo "${s##*_}"
केवल POSIX sh कंस्ट्रक्शंस का उपयोग करके, आप एक समय में एक सीमांकक को पार्स करने के लिए पैरामीटर प्रतिस्थापन निर्माण का उपयोग कर सकते हैं । ध्यान दें कि यह कोड मानता है कि फ़ील्ड की अपेक्षित संख्या है, अन्यथा अंतिम फ़ील्ड दोहराया जाता है।
string='one_two_three_four_five'
remainder="$string"
first="${remainder%%_*}"; remainder="${remainder#*_}"
second="${remainder%%_*}"; remainder="${remainder#*_}"
third="${remainder%%_*}"; remainder="${remainder#*_}"
fourth="${remainder%%_*}"; remainder="${remainder#*_}"
वैकल्पिक रूप से, आप वाइल्डकार्ड विस्तार के साथ एक अनियोजित पैरामीटर प्रतिस्थापन का उपयोग कर सकते हैं और IFS
सीमांकित चरित्र पर सेट किया जाता है (यह केवल तभी काम करता है जब सीमांकक एक एकल नॉन-व्हाट्सएप चरित्र है या यदि कोई व्हाट्सएप अनुक्रम सीमांकक है)।
string='one_two_three_four_five'
set -f; IFS='_'
set -- $string
second=$2; fourth=$4
set +f; unset IFS
यह स्थितिगत मापदंडों को स्पष्ट करता है। यदि आप किसी फ़ंक्शन में ऐसा करते हैं, तो केवल फ़ंक्शन के स्थितीय पैरामीटर प्रभावित होते हैं।
फिर भी एक अन्य दृष्टिकोण read
बिलिन का उपयोग करना है ।
IFS=_ read -r first second third fourth trail <<'EOF'
one_two_three_four_five
EOF
unset IFS
वापस नहीं करता है IFS
डिफ़ॉल्ट करने के लिए। यदि उसके बाद कोई करता है OldIFS="$IFS"
तो OldIFS के अंदर एक अशक्त मूल्य होगा। इसके अलावा, यह मान लिया गया है कि IFS का पिछला मान डिफ़ॉल्ट है, जो नहीं होना बहुत संभव (और उपयोगी) है। एकमात्र सही समाधान old="$IFS"
IFS = "$ पुराने" के साथ स्टोर करना और बाद में पुनर्स्थापित करना है। या ... एक उप-शेल का उपयोग करें (...)
। या, बेहतर अभी तक, मेरा जवाब पढ़ें।
unset IFS
पुनर्स्थापित नहीं करता है IFS
, लेकिन यह डिफ़ॉल्ट प्रभाव के लिए क्षेत्र को विभाजित करता है। हां, यह एक सीमा है, लेकिन आमतौर पर व्यवहार में एक स्वीकार्य है। एक उपधारा के साथ समस्या यह है कि हमें इससे डेटा प्राप्त करने की आवश्यकता है। मैं एक समाधान दिखाता हूं जो राज्य को अंत में नहीं बदलता है, के साथ read
। (यह POSIX गोले में काम करता है, लेकिन IIRC बॉर्न शेल में नहीं है क्योंकि यह read
यहाँ-दस्तावेज़ के कारण उप- भाग में चलेगा ।) <<<
जैसा कि आप उत्तर में उपयोग कर रहे हैं, जो केवल ksh / bash / zsh में काम करता है।
user/my_folder/[this_is_my_file]*
? जब मैं इन चरणों का पालन करता हूं तो मुझे क्या मिलता है[this_is_my_file]*
/
।
एक awk
जवाब देखना चाहता था , तो यहाँ एक है:
A=$(awk -F_ '{print $2}' <<< 'one_two_three_four_five')
B=$(awk -F_ '{print $4}' <<< 'one_two_three_four_five')
awk -F_ '{print $NF}' <<< 'one_two_3_4_five'
सबसे सरल तरीका (<<< के साथ गोले के लिए) है:
IFS='_' read -r a second a fourth a <<<"$string"
एक शेल के $a
बजाय एक अस्थायी चर का उपयोग करना $_
।
एक पूर्ण स्क्रिप्ट में:
string='one_two_three_four_five'
IFS='_' read -r a second a fourth a <<<"$string"
echo "$second $fourth"
कोई IFS नहीं बदल रहा है, set -f
(Pathname विस्तार) के साथ कोई समस्या नहीं है, स्थितिगत मापदंडों में कोई बदलाव नहीं ("$ @")।
सभी गोले के लिए पोर्टेबल समाधान के लिए (हाँ, सभी POSIX शामिल) IFS को बदलने के बिना या set -f
, (थोड़ा और अधिक जटिल) heredoc समकक्ष का उपयोग करें:
string='one_two_three_four_five'
IFS='_' read -r a second a fourth a <<-_EOF_
$string
_EOF_
echo "$second $fourth"
यह समझें कि यह समाधान (दोनों यहाँ-डॉक्टर और उपयोग के <<<
सभी नए सिरे को हटा देगा।
और यह कि इसे "वन लाइनर" वैरिएबल सामग्री के लिए डिज़ाइन किया गया है।
मल्टी-लाइनर्स के लिए समाधान संभव है लेकिन अधिक जटिल निर्माणों की आवश्यकता है।
बश संस्करण 4.4 में एक बहुत ही सरल समाधान संभव है
readarray -d _ -t arr <<<"$string"
echo "array ${arr[1]} ${arr[3]}" # array numbers are zero based.
POSIX गोले के लिए कोई समकक्ष नहीं है, क्योंकि कई POSIX गोले में सरणियाँ नहीं हैं।
उन गोले के लिए, जिनके पास सरणियाँ सरल हो सकती हैं:
(attsh, lksh, mksh, ksh, और bash में काम किया गया परीक्षण)
set -f; IFS=_; arr=($string)
लेकिन चर और विकल्पों को रखने और रीसेट करने के लिए बहुत सी अतिरिक्त पाइपलाइनों के साथ:
string='one_* *_three_four_five'
case $- in
*f*) noglobset=true; ;;
*) noglobset=false;;
esac
oldIFS="$IFS"
set -f; IFS=_; arr=($string)
if $noglobset; then set -f; else set +f; fi
echo "two=${arr[1]} four=${arr[3]}"
Zsh में, सरणियाँ 1 में शुरू होती हैं, और डिफ़ॉल्ट रूप से स्ट्रिंग को विभाजित नहीं करती हैं।
इसलिए इस काम को करने के लिए कुछ बदलाव करने की जरूरत है।
read
रूप में लंबे समय के रूप में सरल कर रहे हैं जब तक ओपी 76 वें और 127 वें तत्वों को एक लंबी स्ट्रिंग से बाहर निकालना नहीं चाहता ...
readarray
उस स्थिति के लिए उपयोग करना आसान हो सकता है।
आपके साथ zsh
स्ट्रिंग को (पर _
) एक सरणी में विभाजित किया जा सकता है :
elements=(${(s:_:)string})
और फिर प्रत्येक / किसी भी तत्व को ऐरे इंडेक्स के माध्यम से एक्सेस करें:
print -r ${elements[4]}
ध्यान रखें कि zsh
(विपरीत ksh
/ bash
) सरणी सूचकांक 1 से शुरू होते हैं ।
set -f
पहले समाधान के लिए चेतावनी जोड़ना याद रखें । ... तारांकन *
शायद?
set -f
? मैं उपयोग नहीं कर रहा हूँ read
/ IFS
। मेरे समाधान को एक स्ट्रिंग की तरह *_*_*
या जो भी कोशिश करें ...
एक और जागृत उदाहरण; समझने में सरल।
A=\`echo one_two_three_four_five | awk -F_ '{print $1}'\`
B=\`echo one_two_three_four_five | awk -F_ '{print $2}'\`
C=\`echo one_two_three_four_five | awk -F_ '{print $3}'\`
... and so on...
चर के साथ भी इस्तेमाल किया जा सकता है।
मान लीजिए:
this_str = "one_two_three_four_five"
फिर निम्नलिखित कार्य करता है:
A = `प्रतिध्वनि $ {this_str} | awk -F_ '{प्रिंट $ 1}' `
B =` प्रतिध्वनि $ {this_str} | awk -F_ '{प्रिंट $ 2}' `
C =` प्रतिध्वनि $ {this_str} | awk -F_ '{प्रिंट $ 3}' `
... इत्यादि ...