शेल स्क्रिप्टिंग में स्ट्रिंग के पहले दो अक्षरों को कैसे निकाला जाए?


123

उदाहरण के लिए, दिया गया:

USCAGoleta9311734.5021-120.1287855805

मैं सिर्फ निकालना चाहता हूं:

US

6
सबको धन्यवाद। मैंने 'cut -c1-2' का उपयोग करके समाप्त किया, ईमानदारी से मुझे पता नहीं था कि 'cut' भी था। मैं यह कहना चाहता हूं कि मैं कमांड लाइन में काफी अनुभवी हूं - लेकिन जाहिर तौर पर मुझे बहुत कुछ सीखना है।
ग्रेग

1
@Greg, बस इस बात से अवगत रहें कि कट को एक अलग प्रक्रिया के रूप में चलाया जाता है - यह मेरे जवाब में मेरे साथ पोस्ट किए गए आंतरिक-बैश समाधान की तुलना में धीमा होगा। जब तक आप विशाल डेटा सेट को संसाधित नहीं कर रहे हैं तब तक कोई फर्क नहीं पड़ेगा, लेकिन आपको इसे ध्यान में रखना होगा।
paxdiablo

वास्तव में संपादित करें , मुझे लगता है कि कोड की इस पंक्ति को संभवतः प्रति रिपोर्ट लगभग 50,000 बार निष्पादित किया जाएगा। इसलिए मैं सिर्फ आंतरिक बैश पद्धति के साथ जा सकता हूं - जैसा कि आपने कहा कि कुछ आवश्यक संसाधनों को बचाएगा।
ग्रेग

जवाबों:


180

संभवतः सबसे कुशल विधि, यदि आप bashशेल का उपयोग कर रहे हैं (और आप अपनी टिप्पणियों के आधार पर दिखाई देते हैं), तो पैरामीटर विस्तार के उप-स्ट्रिंग संस्करण का उपयोग करना है:

pax> long="USCAGol.blah.blah.blah"
pax> short="${long:0:2}" ; echo "${short}"
US

यह shortपहले दो अक्षर होंगे long। यदि longदो वर्णों से छोटा है, तो shortइसके समान होगा।

यह शेल विधि आमतौर पर बेहतर है यदि आप इसे बहुत अधिक करने जा रहे हैं (जैसा कि आप रिपोर्ट के अनुसार प्रति माह 50,000 बार) जैसे कि कोई प्रक्रिया निर्माण ओवरहेड नहीं है। सभी समाधान जो बाहरी कार्यक्रमों का उपयोग करते हैं, उस ओवरहेड से पीड़ित होंगे।

यदि आप न्यूनतम लंबाई सुनिश्चित करना चाहते हैं , तो आप इसे कुछ इस तरह से हाथ से पहले निकाल सकते हैं:

pax> long="A"
pax> tmpstr="${long}.."
pax> short="${tmpstr:0:2}" ; echo "${short}"
A.

यह सुनिश्चित करेगा कि लंबाई में दो वर्णों से कम कुछ भी समय के साथ दाईं ओर गढ़ा गया था (या कुछ और, बस बनाने के दौरान उपयोग किए गए चरित्र को बदलकर tmpstr)। यह स्पष्ट नहीं है कि आपको इसकी आवश्यकता है, लेकिन मुझे लगा कि मैं इसे पूर्णता के लिए रखूंगा।


कहा जा रहा है कि, बाहरी कार्यक्रमों के साथ ऐसा करने के लिए कई तरीके हैं (जैसे कि यदि आपके पास bashउपलब्ध नहीं है ), जिनमें से कुछ निम्नलिखित हैं:

short=$(echo "${long}" | cut -c1-2)
short=$(echo "${long}" | head -c2)
short=$(echo "${long}" | awk '{print substr ($0, 0, 2)}'
short=$(echo "${long}" | sed 's/^\(..\).*/\1/')

पहले दो ( cutऔर head) सिंगल-लाइन स्ट्रिंग के लिए समान हैं - वे मूल रूप से दोनों आपको पहले दो अक्षर वापस देते हैं। वे अलग-अलग हैं जो cutआपको प्रत्येक पंक्ति headके पहले दो अक्षर देगा और आपको पूरे इनपुट के पहले दो अक्षर देगा

तीसरा awkपहले दो वर्णों को निकालने के लिए उप-स्ट्रिंग फ़ंक्शन का उपयोग करता है और चौथा पहले दो वर्णों को पकड़ने और उनके साथ पूरी पंक्ति को बदलने के लिए sedकैप्चर समूहों (उपयोग ()और \1) का उपयोग करता है। वे दोनों समान हैं cut- वे इनपुट में प्रत्येक पंक्ति के पहले दो अक्षर देते हैं।

इस बात से कोई भी फर्क नहीं पड़ता कि आपको यकीन है कि आपका इनपुट सिंगल लाइन है, इन सबका प्रभाव समान है।


मैं मामले में printf '%s'इसके बजाय उपयोग करना चाहूंगा echo, अगर स्ट्रिंग में अजीब आकर्षण हैं: stackoverflow.com/a/40423558/895245 के लिए POSIX जुनूनी: head -cPOSIX नहीं है, cut -cऔर awk substr, sed \1निश्चित नहीं हैं।
सिरो सेंटिल्ली 郝海东 i iro i 法轮功 '

1
@CiroSantilli 新疆 IC IC 996ICU S S प्रिंटफ का उपयोग करते हुए, आपको अतिरिक्त कार्यक्रम की भी आवश्यकता नहीं है। मेरा जवाब देखिए ।
bschlueter

60

सबसे आसान तरीका है

${string:position:length}

जहां इस अर्क $lengthसे सबस्ट्रिंग $stringपर $position

यह एक बैश बिलिन है, इसलिए जाग या सेड की आवश्यकता नहीं है।


यह छोटा, मीठा और सबसे आसान तरीका है सबस्ट्रिंग।
ani627

34

आपके पास कई अच्छे जवाब मिल गया है और मैं अपने आप को builtin बैश के साथ जाना चाहते हैं, लेकिन जब से तुम के बारे में पूछा sedऔर awkऔर ( लगभग उन पर आधारित) कोई और की पेशकश की समाधान, मैं तुम्हें इन प्रदान करते हैं:

echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}'

तथा

echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/'

awkएक काफी स्पष्ट होना चाहिए, लेकिन यहाँ की व्याख्या दी गई sedएक:

  • स्थानापन्न "s /"
  • समूह "()" किसी भी वर्ण के दो "" "पंक्ति के प्रारंभ में" ^ "और उसके बाद किसी भी वर्ण"। बार-बार शून्य या अधिक बार "*" (कुछ विशेष वर्णों से बचने के लिए बैकस्लैम की आवश्यकता होती है)
  • पहले (और केवल, इस मामले में) समूह की सामग्री "/" द्वारा (यहाँ बैकस्लैश एक विशेष उप-अभिव्यक्ति का जिक्र करते हुए पलायन है)
  • किया हुआ "/"

1
Awk स्ट्रिंग्स में index 1 पर शुरू होता है, इसलिए आपको इसका उपयोग करना चाहिए substr($0,1,2)
इसहाक

8

यदि आप में हैं bash, तो आप कह सकते हैं:

bash-3.2$ var=abcd
bash-3.2$ echo ${var:0:2}
ab

यह सिर्फ तुम क्या जरूरत हो सकती है ...


सबसे आसान और सबसे सरल जवाब!
अलोहा

7

बस grep:

echo 'abcdef' | grep -Po "^.."        # ab

मेरी जरूरतों को पूरा करता है। आप -Pइसे छोटा करने के विकल्प को हटा सकते हैं । सभी regexs उस पैटर्न को समझेंगे।
डेट्रॉसमैन

6

आप उपयोग कर सकते हैं printf:

$ original='USCAGoleta9311734.5021-120.1287855805'
$ printf '%-.2s' "$original"
US

5

colrm - किसी फ़ाइल से कॉलम निकालें

पहले दो वर्णों को छोड़ने के लिए, बस 3 से शुरू होने वाले कॉलम को हटा दें

cat file | colrm 3

4

वास्तव में काफी देर हो चुकी है लेकिन यहाँ यह है

sed 's/.//3g'

या

awk NF=1 FPAT=..

या

perl -pe '$_=unpack a2'

2

यदि आप शेल स्क्रिप्टिंग का उपयोग करना चाहते हैं और नॉन-पॉज़िक्स एक्सटेंशन (जैसे तथाकथित बशीज़) पर भरोसा नहीं करते हैं, तो आप उन तकनीकों का उपयोग कर सकते हैं, जिन्हें बाहरी उपकरण जैसे कि grep, sed, cut, awk, आदि की आवश्यकता नहीं है, जो अपनी स्क्रिप्ट को कम कुशल बनाओ। शायद दक्षता और पॉज़िक्स पोर्टेबिलिटी आपके उपयोग के मामले में महत्वपूर्ण नहीं है। लेकिन अगर यह (या सिर्फ एक अच्छी आदत के रूप में) है, तो आप शेल पैरामीटर के पहले दो अक्षरों को निकालने के लिए निम्न पैरामीटर विस्तार विकल्प विधि का उपयोग कर सकते हैं :

$ sh -c 'var=abcde; echo "${var%${var#??}}"'
ab

यह पहले दो वर्णों (यह हिस्सा है) को हटाने के लिए "सबसे छोटा उपसर्ग" पैरामीटर विस्तार का उपयोग करता है ${var#??}, फिर मूल से सभी-लेकिन-पहले-दो-वर्ण स्ट्रिंग को निकालने के लिए "सबसे छोटा प्रत्यय" पैरामीटर विस्तार ( ${var%भाग)। मूल्य।

इस विधि को पहले इस उत्तर में वर्णित किया गया था "शेल = चेक करें कि क्या चर #" प्रश्न से शुरू होता है। यह उत्तर कुछ इसी तरह के पैरामीटर विस्तार के तरीकों का भी वर्णन करता है जो कि थोड़े अलग संदर्भ में उपयोग किए जा सकते हैं जो कि यहां मूल प्रश्न पर लागू होता है।


सबसे अच्छा जवाब, शीर्ष पर होना चाहिए। कोई कांटा नहीं, कोई हरामी नहीं। डैश जैसे छोटे गोले के साथ भी काम करता है।
शाम

1

यदि आपका सिस्टम एक अलग शेल (नहीं bash) का उपयोग कर रहा है , लेकिन आपके सिस्टम में है bash, तो आप अभी भी एक वेरिएबल के साथ bashइनवाइट करके स्ट्रिंग के हेरफेर का उपयोग कर सकते हैं bash:

strEcho='echo ${str:0:2}' # '${str:2}' if you want to skip the first two characters and keep the rest
bash -c "str=\"$strFull\";$strEcho;"

यह मुख्य उत्तर के रूप में एक ही विधि का उपयोग करता है , केवल bashअगर आप पहले से ही इसका उपयोग नहीं कर रहे हैं , तो इसका उपयोग करें।
पालसीम

दुर्भाग्य से, यह किसी अन्य प्रक्रिया को लागू करने के ओवरहेड के साथ आता है, लेकिन कभी-कभी यह ओवरहेड सादगी और परिचितता से अधिक मायने नहीं रखता है।
पालसीम

1

बस मज़े के लिए बीमार कुछ जोड़ते हैं, हालांकि वे जटिल और बेकार हैं, उनका उल्लेख नहीं किया गया था:

head -c 2 <( echo 'USCAGoleta9311734.5021-120.1287855805')

echo 'USCAGoleta9311734.5021-120.1287855805' | dd bs=2 count=1 status=none

sed -e 's/^\(.\{2\}\).*/\1/;' <( echo 'USCAGoleta9311734.5021-120.1287855805')

cut -c 1-2 <( echo 'USCAGoleta9311734.5021-120.1287855805')

python -c "print(r'USCAGoleta9311734.5021-120.1287855805'[0:2])"

ruby -e 'puts "USCAGoleta9311734.5021-120.1287855805"[0..1]'


0

अगर मिस्ट्रिंग = USCAGoleta9311734.5021-120.1287855805

print substr(mystring,0,2)

यूएस प्रिंट करेगा

जहां 0 प्रारंभ स्थिति है और 2 यह है कि मैनी चार्ट कैसे पढ़ें


कहो ... यह GW-BASIC नहीं है? ओह, रुको, वह awk। क्षमा करें, मैं पहले नहीं बता सकता।
अगली सूचना तक रोक दिया गया।

0

क्या यह आपके बाद है?

my $string = 'USCAGoleta9311734.5021-120.1287855805';

my $first_two_chars = substr $string, 0, 2;

रेफरी: जड़


1
यह देखते हुए कि वह इसे शेल से बुला रहा है, एक बेहतर रूप होगाperl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'
चास।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.