एक सीमांकक की पहली घटना से विभाजित विभाजन


54

मेरे पास अगले प्रारूप में एक स्ट्रिंग है

id;some text here with possible ; inside

और पहली घटना से इसे 2 तारों में विभाजित करना चाहते हैं ;। तो, यह होना चाहिए: idऔरsome text here with possible ; inside

मुझे पता है कि स्ट्रिंग को कैसे विभाजित किया जाए (उदाहरण के लिए, साथ cut -d ';' -f1), लेकिन यह अधिक भागों में विभाजित होगा क्योंकि मेरे पास ;बाएं भाग के अंदर है।


स्ट्रिंग विभाजित होने के बाद आप "आईडी" के साथ क्या करना चाहते हैं? क्या आप इसे किसी वैरिएबल को असाइन करना चाहते हैं, इसका प्रिंट आउट निकाल सकते हैं, आदि।
कैओस

मेरे पास 2 चर हैं: idऔरstring
gakhov

जवाबों:


65

cut इसके लिए एक उपयुक्त उपकरण की तरह लगता है:

bash-4.2$ s='id;some text here with possible ; inside'

bash-4.2$ id="$( cut -d ';' -f 1 <<< "$s" )"; echo "$id"
id

bash-4.2$ string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"
some text here with possible ; inside

लेकिन readऔर भी उपयुक्त है:

bash-4.2$ IFS=';' read -r id string <<< "$s"

bash-4.2$ echo "$id"
id

bash-4.2$ echo "$string"
some text here with possible ; inside

3
महान! यह एक सम्मोहन की तरह काम करता है! मैं readका उपयोग कर रहा हूँ के बाद से मैं का चयन करेंगे bash। शुक्रिया @manatwork!
गॉकोव

cutदृष्टिकोण ही काम करते हैं जब "$ s" नई पंक्ति वर्ण नहीं होगा। रीड किसी भी बॉर्न जैसे शेल में है। <<< आरसी, zsh और बैश और ksh93 के हाल के संस्करणों में है और वह है जो मानक नहीं है।
स्टीफन चेज़लस

ओह, आप सही हैं @StephaneChazelas। मेरा मन में था -aजब उल्लेख किसी कारण से bash's read। (जाहिर है यहां कोई फायदा नहीं।)
मैनावर्क

मैं यह उल्लेख करना भूल गया कि यदि $ s में newline वर्ण हैं, तो रीड एप्रोच काम नहीं करता है। मैंने अपना जवाब जोड़ दिया है।
स्टीफन चेज़लस

1
मैं कमांड -f 2-में ट्रेलिंग डैश पर जोर देना चाहूंगा string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"। यह वह है जो प्रिंटआउट के लिए स्ट्रिंग में शेष सीमांकक को अनदेखा करता है। स्पष्ट नहीं है जबcut
स्टेट

17

किसी भी मानक श के साथ (बाश सहित):

sep=';'
case $s in
  (*"$sep"*)
    before=${s%%"$sep"*}
    after=${s#*"$sep"}
    ;;
  (*)
    before=$s
    after=
    ;;
esac

readआधारित समाधान एकल वर्ण के लिए काम करेंगे (और कुछ गोले, एकल-बाइट के साथ) $sepअंतरिक्ष, टैब या न्यूलाइन के अलावा अन्य मूल्यों और केवल अगर $sन्यूलाइन वर्ण शामिल नहीं हैं।

cutआधारित समाधान केवल तभी काम करेंगे जब $sन्यूलाइन वर्ण न हों।

sedसमाधान तैयार किए जा सकते हैं जो किसी भी मूल्य के सभी कोने के मामलों को संभालते हैं $sep, लेकिन जब तक उस पर शेल में अंतर्निहित समर्थन नहीं होता है, तब तक यह मूल्य नहीं है।


6

जैसा कि आपने उल्लेख किया है कि आप आईडी और स्ट्रिंग को मान निर्दिष्ट करना चाहते हैं

पहले अपने पैटर्न को एक चर में निर्दिष्ट करें (str कहो)

    str='id;some text here with possible ; inside'
    id=${str%%;} 
    string=${str#;}

अब आपके पास संबंधित चर में आपके मान हैं


यदि आप एक कमांड से अपना पैटर्न प्राप्त कर रहे हैं some_command, तो सेट का उपयोग करें - , फिर आपका पैटर्न $ 1 में संग्रहीत हो जाएगा और उपरोक्त के बजाय 1 के साथ उपरोक्त कोड का उपयोग करेगा
user1678213

यह उत्तर @StephaneChazelas से कैसे भिन्न है?
बर्नहार्ड

4

अन्य समाधानों के अतिरिक्त, आप कुछ regexआधारित कोशिश कर सकते हैं :

a="$(sed 's/;.*//' <<< "$s")"
b="$(sed 's/^[^;]*;//' <<< "$s")"

या आप वास्तव में क्या करने की कोशिश कर रहे हैं उसके आधार पर, आप उपयोग कर सकते हैं

sed -r 's/^([^;]*);(.*)/\1 ADD THIS TEXT BETWEEN YOUR STRINGS \2/'

जहाँ \1और \2जिन दो पदार्थों को आप चाहते थे उनमें शामिल हैं।


1

मानक बैश में समाधान:

    text='id;some text here with possible ; inside'
    text2=${text#*;}
    text1=${text%"$text2"}

    echo $text1
    #=> id;
    echo $text2
    #=> some text here with possible ; insideDD
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.