बैश में सबस्ट्रिंग निकालें


727

प्रपत्र में फ़ाइल नाम दिए जाने पर someletters_12345_moreleters.ext, मैं 5 अंकों को निकालना चाहता हूं और उन्हें एक चर में डाल देना चाहता हूं।

तो इस बिंदु पर जोर देने के लिए, मेरे पास x वर्णों का एक फ़ाइल नाम है, फिर पाँच अंकीय अनुक्रम दोनों ओर से एकल अंडरस्कोर से घिरा हुआ है और फिर x संख्या वर्णों का एक और सेट। मैं 5 अंकों की संख्या लेना चाहता हूं और उसे एक चर में डाल देता हूं।

मुझे विभिन्न तरीकों की संख्या में बहुत दिलचस्पी है जो इसे पूरा कर सकते हैं।


5
जेबी का जवाब स्पष्ट रूप से वोटों को जीत रहा है - स्वीकृत उत्तर को बदलने का समय?
जेफ

3
अधिकांश उत्तर आपके प्रश्न का उत्तर नहीं देते हैं क्योंकि प्रश्न अस्पष्ट है। "मेरे पास वर्णों की x संख्या के साथ एक फ़ाइल नाम है, फिर पाँच अंकीय अनुक्रम जो दोनों ओर एक एकल अंडरस्कोर से घिरा हुआ है, फिर वर्णों की संख्या का एक और समुच्चय" । उस परिभाषा के अनुसार abc_12345_def_67890_ghi_defएक वैध इनपुट है। आप क्या होना चाहते हैं? मान लें कि केवल एक 5 अंक अनुक्रम है। आपके पास इनपुट की परिभाषा के आधार पर अभी भी abc_def_12345_ghi_jklया 1234567_12345_1234567या 12345d_12345_12345eमान्य इनपुट है, और नीचे दिए गए अधिकांश उत्तर इसे संभाल नहीं पाएंगे।
gman

2
इस प्रश्न का एक उदाहरण इनपुट है जो बहुत विशिष्ट है। उसके कारण, इस विशेष मामले के लिए बहुत सारे विशिष्ट उत्तर मिले (केवल अंक, एक ही _सीमांकक, इनपुट जिसमें लक्ष्य स्ट्रिंग केवल एक बार होता है आदि)। सबसे अच्छे (सबसे सामान्य और सबसे तेज़) उत्तर में 10 साल बाद केवल 7 अपवोट्स हैं, जबकि अन्य सीमित उत्तरों में सैकड़ों हैं। मुझे डेवलपर्स में विश्वास खो देता है
Dan

जवाबों:


691

कट का उपयोग करें :

echo 'someletters_12345_moreleters.ext' | cut -d'_' -f 2

अधिक सामान्य:

INPUT='someletters_12345_moreleters.ext'
SUBSTRING=$(echo $INPUT| cut -d'_' -f 2)
echo $SUBSTRING

1
अधिक सामान्य उत्तर वही है जिसकी मुझे तलाश थी, धन्यवाद
बेरेक ब्रायन

71
-F झंडा 1-आधारित सूचकांकों को लेता है, 0-आधारित सूचकांकों के बजाय एक प्रोग्रामर का उपयोग किया जाएगा।
मैथ्यू जी

2
INPUT = someletters_12345_moreleters.ext SUBSTRING = $ (इको $ INPUT | cut -d'_ '-f 2) इको $ SUBSTRING
मणि गहराक

3
echoजब तक आप यह सुनिश्चित न कर लें कि चर में अनियमित व्हाट्सएप या शेल मेटाचैकर नहीं हो सकता है, तब तक आप तर्कों के आसपास दोहरे उद्धरण चिह्नों का उपयोग करें। आगे देखें stackoverflow.com/questions/10067266/…
tripleee

'-F' के बाद की संख्या '2' को विकल्प के दूसरे सेट को निकालने के लिए शेल को बताना है।
संडुन

1085

यदि x स्थिर है, तो निम्न पैरामीटर विस्तार प्रतिस्थापन निष्कर्षण करता है:

b=${a:12:5}

जहां 12 ऑफसेट (शून्य-आधारित) है और 5 लंबाई है

यदि अंक के चारों ओर के अंडरस्कोर इनपुट में एकमात्र होते हैं, तो आप उपसर्ग और प्रत्यय (क्रमशः) को दो चरणों में बंद कर सकते हैं:

tmp=${a#*_}   # remove prefix ending in "_"
b=${tmp%_*}   # remove suffix starting with "_"

यदि अन्य अंडरस्कोर हैं, तो यह संभव है, वैसे भी अधिक मुश्किल है। अगर किसी को पता है कि एक ही अभिव्यक्ति में दोनों विस्तार कैसे करें, तो मैं भी जानना चाहता हूं।

प्रस्तुत दोनों समाधान शुद्ध बाश हैं, जिसमें कोई भी प्रक्रिया शामिल नहीं है, इसलिए बहुत तेज है।


18
bash: ${${a#*_}%_*}: bad substitutionमेरे GNU बैश 4.2.45 पर @SpencerRathbun
जेबी

2
@jonnyB, अतीत में कुछ समय जिसने काम किया। मुझे मेरे सहकर्मियों ने बताया कि यह बंद हो गया, और उन्होंने इसे एक सेड कमांड या कुछ और के रूप में बदल दिया। इतिहास में इसे देखते हुए, मैं इसे एक shस्क्रिप्ट में चला रहा था , जो शायद पानी का छींटा था। इस समय मैं इसे अब और काम नहीं कर सकता।
स्पेंसर रथबुन

22
जेबी, आपको स्पष्ट करना चाहिए कि "12" ऑफसेट (शून्य-आधारित) है और "5" लंबाई है। इसके अलावा, @gontard के लिंक के लिए +1 जो इसे पूरा करता है!
डॉकटोर जे।

1
इसे "sh run.sh" के रूप में स्क्रिप्ट के अंदर चलाने पर, किसी को खराब प्रतिस्थापन त्रुटि मिल सकती है। उससे बचने के लिए, run.sh (chmod + x run.sh) के लिए अनुमतियां बदलें और फिर स्क्रिप्ट को "./run.sh" के रूप में चलाएं
अंकुर

2
ऑफसेट परम नकारात्मक भी हो सकता है, BTW। आपको बस यह ध्यान रखना है कि इसे कोलन में न गाड़ें, या बैश इसे :-"डिफ़ॉल्ट वैल्यूज़" प्रतिस्थापन के रूप में व्याख्या करेगा । तो ${a: -12:5}अंत से 5 वर्ण 12 वर्ण ${a: -12:-5}और अंत -12 और अंत -5 के बीच 7 वर्ण उत्पन्न करता है ।
जेबी

96

जेनेरिक सॉल्यूशन जहां इस तरह के सीक्वेंस में से पहले नंबर का उपयोग करके फ़ाइल नाम में कहीं भी हो सकता है:

number=$(echo $filename | egrep -o '[[:digit:]]{5}' | head -n1)

एक चर का एक हिस्सा निकालने के लिए एक और समाधान:

number=${filename:offset:length}

यदि आपके फ़ाइलनाम में हमेशा वह प्रारूप है जिसका stuff_digits_...उपयोग आप awk कर सकते हैं:

number=$(echo $filename | awk -F _ '{ print $2 }')

फिर भी अंकों को छोड़कर सब कुछ हटाने का एक और उपाय

number=$(echo $filename | tr -cd '[[:digit:]]')

2
क्या होगा अगर मैं फ़ाइल की अंतिम पंक्ति से अंक / शब्द निकालना चाहता हूं।
एक सहरा

92

बस उपयोग करने का प्रयास करें cut -c startIndx-stopIndx


2
क्या StartIndex-lastIndex - 1 जैसा कुछ है?
निकल्स

1
@ नीकल्स इन बैश, startIndx-$((lastIndx-1))
प्रोलि

3
start=5;stop=9; echo "the rain in spain" | cut -c $start-$(($stop-1))
भूरे .179

1
समस्या यह है कि इनपुट गतिशील है क्योंकि मैं इसे प्राप्त करने के लिए पाइप का उपयोग करता हूं इसलिए यह मूल रूप से है। git log --oneline | head -1 | cut -c 9-(end -1)
निकलैस

यह कट के साथ किया जा सकता है अगर दो भागों में तोड़ के रूप में line=git log --online | सिर -1` && गूंज $ लाइन | कटौती -c 9 - $ (($ {# लाइन} -1)) `लेकिन इस विशेष मामले में, बेहतर हो सकता है का उपयोग करने के लिए sed के रूप मेंgit log --oneline | head -1 | sed -e 's/^[a-z0-9]* //g'
brown.2179

34

यदि कोई व्यक्ति अधिक कठोर जानकारी चाहता है, तो आप उसे इस तरह मैन बैश में भी खोज सकते हैं

$ man bash [press return key]
/substring  [press return key]
[press "n" key]
[press "n" key]
[press "n" key]
[press "n" key]

परिणाम:

$ {पैरामीटर: ऑफसेट}
       $ {पैरामीटर: ऑफसेट: लंबाई}
              पदार्थ का विस्तार। की लंबाई के पात्रों तक फैलता है
              ऑफसेट द्वारा निर्दिष्ट चरित्र पर शुरू होने वाला पैरामीटर। अगर
              लंबाई छोड़ी गई है, पैरामीटर स्टार्टिंग के विकल्प का विस्तार करता है
              ऑफसेट द्वारा निर्दिष्ट चरित्र पर आईएनजी। लंबाई और ऑफसेट हैं
              अंकगणितीय अभिव्यक्तियाँ (नीचे देखें ARALMETIC EVALUATION) अगर
              ऑफ़सेट शून्य से कम संख्या का मूल्यांकन करता है, मान का उपयोग किया जाता है
              पैरामीटर के मूल्य के अंत से एक ऑफसेट के रूप में। अंकगणित
              a से शुरू होने वाले भावों को व्हाट्सएप द्वारा अलग किया जाना चाहिए
              पूर्ववर्ती से: उपयोग डिफ़ॉल्ट से अलग किया जाए
              मूल्यों का विस्तार। यदि लंबाई से कम संख्या का मूल्यांकन करता है
              शून्य, और पैरामीटर @ नहीं है और अनुक्रमित या साहचर्य नहीं है
              सरणी, इसे मूल्य के अंत से ऑफसेट के रूप में व्याख्या की जाती है
              वर्णों की संख्या के बजाय पैरामीटर, और विस्तारक
              सायन दो संतानों के बीच के अक्षर हैं। अगर पैरामीटर है
              @, परिणाम off the पर शुरू होने वाली लंबाई की स्थितिगत पैरामीटर है
              सेट। यदि पैरामीटर एक अनुक्रमित सरणी नाम है, जो @ या के अधीन है
              *, परिणाम सरणी के लंबाई के सदस्यों के साथ शुरू होता है
              $ {पैरामीटर [ऑफसेट]}। एक नकारात्मक ऑफसेट के सापेक्ष लिया जाता है
              निर्दिष्ट सरणी के अधिकतम इंडेक्स से एक अधिक है। विषय-
              एक सहयोगी सरणी के लिए लागू स्ट्रिंग विस्तार unde applied पैदा करता है
              जुर्माना परिणाम। ध्यान दें कि एक नकारात्मक ऑफसेट को अलग किया जाना चाहिए
              कम से कम एक स्थान से बृहदान्त्र से भ्रमित होने से बचने के लिए
              के साथ: - विस्तार। जब तक अनुक्रमण पदार्थ शून्य-आधारित नहीं होता है
              स्थितीय मापदंडों का उपयोग किया जाता है, जिस स्थिति में अनुक्रमण होता है
              डिफ़ॉल्ट रूप से 1 से शुरू होता है। यदि ऑफसेट 0 है, और स्थिति है
              मापदंडों का उपयोग किया जाता है, $ 0 सूची में उपसर्ग किया जाता है।

2
जैसा कि ऊपर कहा गया है, नकारात्मक मूल्यों के साथ एक बहुत ही महत्वपूर्ण चेतावनी: अंकगणित के साथ शुरू होने वाले भाव - पूर्ववर्ती व्हाट्सएप द्वारा अलग किए जाने चाहिए: उपयोग डिफ़ॉल्ट मानों से अलग होने के लिए। तो एक var के अंतिम चार अक्षर पाने के लिए:${var: -4}
sshow करें

26

यहां बताया गया है कि मैं इसे कैसे करूंगा:

FN=someletters_12345_moreleters.ext
[[ ${FN} =~ _([[:digit:]]{5})_ ]] && NUM=${BASH_REMATCH[1]}

स्पष्टीकरण:

बैश विशेष:

नियमित अभिव्यक्तियाँ (आरई): _([[:digit:]]{5})_

  • _ मिलान किए जा रहे स्ट्रिंग के लिए सीमांकन / लंगर मिलान सीमाओं के लिए शाब्दिक हैं
  • () एक कैप्चर ग्रुप बनाएं
  • [[:digit:]] एक चरित्र वर्ग है, मुझे लगता है कि यह खुद के लिए बोलता है
  • {5} पूर्व चरित्र के ठीक पाँच का मतलब है, वर्ग (इस उदाहरण में), या समूह से मेल खाना चाहिए

अंग्रेजी में, आप इसे इस तरह से व्यवहार कर सकते हैं: FNस्ट्रिंग चरित्र द्वारा पुनरावृत्त चरित्र है जब तक हम देखते हैं कि _किस बिंदु पर कब्जा समूह खोला गया है और हम पांच अंकों का मिलान करने का प्रयास करते हैं। यदि वह मिलान इस बिंदु पर सफल होता है, तो कैप्चर समूह फंसे हुए पाँच अंकों को बचाता है। यदि अगला चरित्र ए है _, तो स्थिति सफल होती है, कैप्चर ग्रुप को उपलब्ध कराया जाता है BASH_REMATCHऔर अगला NUM=स्टेटमेंट निष्पादित हो सकता है। यदि मिलान के किसी भी भाग में विफल रहता है, तो सहेजे गए विवरणों का निपटान किया जाता है और चरित्र प्रसंस्करण द्वारा चरित्र को जारी रखा जाता है _। उदाहरण के लिए , FNजहाँ _1 _12 _123 _1234 _12345_, वहाँ एक मैच शुरू होने से पहले चार झूठी शुरुआत होगी।


3
यह एक सामान्य तरीका है जो काम करता है भले ही आपको एक से अधिक चीजें निकालने की आवश्यकता हो, जैसा कि मैंने किया था।
zebediah49

3
यह वास्तव में सबसे सामान्य उत्तर है, और इसे स्वीकार किया जाना चाहिए। यह एक नियमित अभिव्यक्ति के लिए काम करता है, न केवल एक निश्चित स्थान पर या उसी सीमांकक (जो सक्षम करता है cut) के बीच पात्रों की एक स्ट्रिंग । यह किसी बाहरी कमांड को निष्पादित करने पर भी निर्भर नहीं करता है।
डैन डस्केल्सस्क्यू

1
यह उत्तर आपराधिक रूप से कमतर है।
शेपनर

यह भी खूब रही! मैंने अपनी स्थिति के लिए अलग-अलग स्टार्ट / स्टॉप डिलिमिटर्स (_ की जगह) और वेरिएबल लेंथ नंबर ({5} के लिए) का उपयोग करने के लिए इसे अनुकूलित किया। क्या कोई इस काले जादू को तोड़ सकता है और समझा सकता है?
पॉल

1
@Paul मैंने अपने उत्तर में अधिक विवरण जोड़े। उम्मीद है की वो मदद करदे।
nicerobot

21

मुझे आश्चर्य है कि यह शुद्ध बैश समाधान सामने नहीं आया:

a="someletters_12345_moreleters.ext"
IFS="_"
set $a
echo $2
# prints 12345

आप शायद IFS को रीसेट करना चाहते हैं कि यह किस मूल्य से पहले था, या unset IFSबाद में!


1
यह शुद्ध बैश समाधान नहीं है, मुझे लगता है कि यह शुद्ध शेल (/ बिन / श) में काम करता है
kayn

5
+1: आप IFSIFS=_ read -r _ digs _ <<< "$a"; echo "$digs"
परेशान

2
यह pathname विस्तार के अधीन है! (इसलिए यह टूट गया है)।
48 बजे

20

जोर के जवाब पर निर्माण (जो मेरे लिए काम नहीं करता है):

substring=$(expr "$filename" : '.*_\([^_]*\)_.*')

12
रेगुलर एक्सप्रेशंस असली सौदा है जब आपके पास कुछ जटिल होता है और बस अंडरस्कोर गिनना cutयह नहीं होगा।
5:00 पर हांग्जो लेवचुक

12

आवश्यकताओं का पालन

मेरे पास वर्णों की x संख्या के साथ एक फ़ाइल नाम है, फिर एक पाँच अंकीय अनुक्रम जो दोनों तरफ एक एकल अंडरस्कोर से घिरा हुआ है, फिर x संख्या वर्णों का एक और सेट। मैं 5 अंकों की संख्या लेना चाहता हूं और उसे एक चर में डाल देता हूं।

मुझे कुछ grepतरीके मिले जो उपयोगी हो सकते हैं:

$ echo "someletters_12345_moreleters.ext" | grep -Eo "[[:digit:]]+" 
12345

या और अच्छा

$ echo "someletters_12345_moreleters.ext" | grep -Eo "[[:digit:]]{5}" 
12345

और फिर -Poसिंटैक्स के साथ :

$ echo "someletters_12345_moreleters.ext" | grep -Po '(?<=_)\d+' 
12345

या यदि आप इसे ठीक 5 वर्ण बनाना चाहते हैं:

$ echo "someletters_12345_moreleters.ext" | grep -Po '(?<=_)\d{5}' 
12345

अंत में, इसे एक चर में संग्रहीत करने के लिए इसे var=$(command)सिंटैक्स का उपयोग करने की आवश्यकता है ।


2
मेरा मानना ​​है कि आजकल egrep का उपयोग करने की कोई आवश्यकता नहीं है, कमांड ही आपको चेतावनी देता है Invocation as 'egrep' is deprecated; use 'grep -E' instead:। मैंने आपका उत्तर संपादित कर दिया है।
न्यूरोट्रांसमीटर

11

यदि हम की अवधारणा में ध्यान केंद्रित करते हैं:
"एक रन (एक या कई) अंक"

हम संख्या निकालने के लिए कई बाहरी उपकरणों का उपयोग कर सकते हैं।
हम सभी अन्य वर्णों को आसानी से मिटा सकते हैं, या तो sed या tr:

name='someletters_12345_moreleters.ext'

echo $name | sed 's/[^0-9]*//g'    # 12345
echo $name | tr -c -d 0-9          # 12345

लेकिन अगर $ नाम में संख्याओं के कई रन शामिल हैं, तो उपरोक्त विफल हो जाएगा:

यदि "name = someletters_12345_moreleters_323_end.ext", तो:

echo $name | sed 's/[^0-9]*//g'    # 12345323
echo $name | tr -c -d 0-9          # 12345323

हमें नियमित एक्सरेशन (रेगेक्स) का उपयोग करने की आवश्यकता है।
सेडल और पर्ल में केवल पहले रन (12345 नहीं 323) का चयन करने के लिए:

echo $name | sed 's/[^0-9]*\([0-9]\{1,\}\).*$/\1/'
perl -e 'my $name='$name';my ($num)=$name=~/(\d+)/;print "$num\n";'

लेकिन हम इसे सीधे bash (1) में भी कर सकते हैं :

regex=[^0-9]*([0-9]{1,}).*$; \
[[ $name =~ $regex ]] && echo ${BASH_REMATCH[1]}

यह हमें
किसी भी अन्य पाठ / वर्णों से घिरे किसी भी लम्बाई के अंकों के FIRST रन को निकालने की अनुमति देता है ।

नोट : regex=[^0-9]*([0-9]{5,5}).*$;केवल 5 अंकों के रन से मेल खाएगा। :-)

(1) : प्रत्येक छोटे ग्रंथों के लिए एक बाहरी टूल को कॉल करने से तेज़। बड़ी फ़ाइलों के लिए sed या awk के अंदर सभी प्रोसेसिंग करने से तेज़ नहीं है।


10

किसी भी उप-प्रक्रिया के बिना आप कर सकते हैं:

shopt -s extglob
front=${input%%_+([a-zA-Z]).*}
digits=${front##+([a-zA-Z])_}

इसका एक बहुत छोटा संस्करण ksh93 में भी काम करेगा।


9

यहां एक उपसर्ग-प्रत्यय समाधान (जेबी और डैरन द्वारा दिए गए समाधानों के समान) है जो अंकों के पहले ब्लॉक से मेल खाता है और आसपास के अंडरस्कोर पर निर्भर नहीं करता है:

str='someletters_12345_morele34ters.ext'
s1="${str#"${str%%[[:digit:]]*}"}"   # strip off non-digit prefix from str
s2="${s1%%[^[:digit:]]*}"            # strip off non-digit suffix from s1
echo "$s2"                           # 12345

7

मुझे sedरेगेक्स समूहों से निपटने की क्षमता पसंद है :

> var="someletters_12345_moreletters.ext"
> digits=$( echo $var | sed "s/.*_\([0-9]\+\).*/\1/p" -n )
> echo $digits
12345

थोड़ा और सामान्य विकल्प यह नहीं माना जाएगा कि आपके पास _अपने अंकों के अनुक्रम की शुरुआत को चिह्नित करने वाला एक अंडरस्कोर है , इसलिए उदाहरण के लिए आपके अनुक्रम से पहले प्राप्त सभी गैर-संख्याओं को अलग करना s/[^0-9]\+\([0-9]\+\).*/\1/p:।


> man sed | grep s/regexp/replacement -A 2
s/regexp/replacement/
    Attempt to match regexp against the pattern space.  If successful, replace that portion matched with replacement.  The replacement may contain the special  character  &  to
    refer to that portion of the pattern space which matched, and the special escapes \1 through \9 to refer to the corresponding matching sub-expressions in the regexp.

इस पर अधिक, मामले में आप regexps के साथ आश्वस्त नहीं हैं:

  • s _s_ubstitute के लिए है
  • [0-9]+ 1+ अंकों से मेल खाता है
  • \1 रेगेक्स आउटपुट के समूह n.1 के लिंक (समूह 0 पूरे मैच है, समूह 1 इस मामले में कोष्ठक के भीतर का मैच है)
  • p झंडा _p_rinting के लिए है

सभी भागने के संसाधन प्रसंस्करण कार्य \करने के लिए वहाँ हैं sed


6

मेरे उत्तर का इस पर अधिक नियंत्रण होगा कि आप अपनी स्ट्रिंग से क्या चाहते हैं। यहाँ कोड है कि आप 12345अपने स्ट्रिंग से बाहर कैसे निकाल सकते हैं

str="someletters_12345_moreleters.ext"
str=${str#*_}
str=${str%_more*}
echo $str

यह अधिक कुशल होगा यदि आप किसी ऐसी चीज़ को निकालना चाहते हैं जिसमें कोई वर्ण हो abcया जैसे कोई विशेष वर्ण _या -। उदाहरण के लिए: यदि आपका तार इस तरह है और आप वह सब कुछ चाहते हैं, जो someletters_पहले और बाद में है _moreleters.ext:

str="someletters_123-45-24a&13b-1_moreleters.ext"

मेरे कोड के साथ आप उल्लेख कर सकते हैं कि आप वास्तव में क्या चाहते हैं। स्पष्टीकरण:

#*यह मिलान कुंजी सहित पूर्ववर्ती स्ट्रिंग को हटा देगा। यहां हमने जिस कुंजी का उल्लेख किया है _ %वह है मिलान कुंजी सहित निम्नलिखित स्ट्रिंग को हटा देगा। यहाँ हमने जिस कुंजी का उल्लेख किया है वह '_more *' है।

कुछ प्रयोग स्वयं करें और आपको यह दिलचस्प लगेगा।


6

दिया गया परीक्षण। Txt एक फाइल है जिसमें "ABCDEFGHIJKLMNOPQRSTUVWXYZ" है

cut -b19-20 test.txt > test1.txt # This will extract chars 19 & 20 "ST" 
while read -r; do;
> x=$REPLY
> done < test1.txt
echo $x
ST

यह उस विशेष इनपुट के लिए अत्यंत विशिष्ट है। सामान्य प्रश्न का एकमात्र सामान्य समाधान (जिसे ओपी को पूछना चाहिए था) एक regexp का उपयोग करना है
डैन डैस्कलेस्क्यू

3

ठीक है, यहाँ एक खाली स्ट्रिंग के साथ शुद्ध पैरामीटर प्रतिस्थापन है। कैविएट यह है कि मैंने कुछ अक्षरों और अधिकताओं को केवल वर्णों के रूप में परिभाषित किया है । यदि वे अल्फ़ान्यूमेरिक हैं, तो यह काम नहीं करेगा जैसा कि यह है।

filename=someletters_12345_moreletters.ext
substring=${filename//@(+([a-z])_|_+([a-z]).*)}
echo $substring
12345

2
भयानक लेकिन कम से कम bash v4 की आवश्यकता है
olibre 14:25

2

पीएचपी के समान ('एबडेफग', 2-1, 3) के समान:

echo 'abcdefg'|tail -c +2|head -c 3

यह उस इनपुट के लिए अत्यंत विशिष्ट है। सामान्य प्रश्न का एकमात्र सामान्य समाधान (जिसे ओपी को पूछना चाहिए था) एक regexp का उपयोग करना है
डैन डस्केल्सस्क्यू

1

बैश बिलिन 'expr' कमांड भी है:

INPUT="someletters_12345_moreleters.ext"  
SUBSTRING=`expr match "$INPUT" '.*_\([[:digit:]]*\)_.*' `  
echo $SUBSTRING

4
exprबिलियन नहीं है।
ग्नौरफ_गनीउरफ

1
यह भी =~समर्थित ऑपरेटर के प्रकाश में आवश्यक नहीं है [[
जुआन

1

थोड़ी देर हो गई, लेकिन मैं अभी इस समस्या से भाग गया और निम्नलिखित पाया:

host:/tmp$ asd=someletters_12345_moreleters.ext 
host:/tmp$ echo `expr $asd : '.*_\(.*\)_'`
12345
host:/tmp$ 

मैंने इसका उपयोग एक अंतर्निहित प्रणाली पर मिलीसेकंड रिज़ॉल्यूशन प्राप्त करने के लिए किया है जिसमें तारीख के लिए% N नहीं है:

set `grep "now at" /proc/timer_list`
nano=$3
fraction=`expr $nano : '.*\(...\)......'`
$debug nano is $nano, fraction is $fraction

1

एक बैश समाधान:

IFS="_" read -r x digs x <<<'someletters_12345_moreleters.ext'

यह एक चर बुलाया जाएगा x। संस्करण xको var में बदला जा सकता है _

input='someletters_12345_moreleters.ext'
IFS="_" read -r _ digs _ <<<"$input"

1

जेएस और जावा कार्यान्वयन के समान विशिष्ट अंत। यदि आप यह नहीं चाहते हैं तो +1 निकालें।

substring() {
    local str="$1" start="${2}" end="${3}"

    if [[ "$start" == "" ]]; then start="0"; fi
    if [[ "$end"   == "" ]]; then end="${#str}"; fi

    local length="((${end}-${start}+1))"

    echo "${str:${start}:${length}}"
} 

उदाहरण:

    substring 01234 0
    01234
    substring 012345 0
    012345
    substring 012345 0 0
    0
    substring 012345 1 1
    1
    substring 012345 1 2
    12
    substring 012345 0 1
    01
    substring 012345 0 2
    012
    substring 012345 0 3
    0123
    substring 012345 0 4
    01234
    substring 012345 0 5
    012345

अधिक उदाहरण कॉल:

    substring 012345 0
    012345
    substring 012345 1
    12345
    substring 012345 2
    2345
    substring 012345 3
    345
    substring 012345 4
    45
    substring 012345 5
    5
    substring 012345 6

    substring 012345 3 5
    345
    substring 012345 3 4
    34
    substring 012345 2 4
    234
    substring 012345 1 3
    123

आपका स्वागत है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.