एक स्ट्रिंग को बैश में अनुक्रमित करें


15

मैं sh / bash में इंडेक्स द्वारा स्ट्रिंग का संदर्भ कैसे दे सकता हूं? यही है, मूल रूप से इसे विभाजित करना।

मैं एक फ़ाइल नाम के 5 वर्णों को हटाने की कोशिश कर रहा हूं। सभी नामों की संरचना है: name_nr_code। मैं 5 अल्फ़ान्यूमेरिक कोड बिट को निकालने की कोशिश कर रहा हूं। name_nr_हमेशा 10 वर्ण का होता है।

जैसी चीज है;

for i in * ; do mv "$i" "$i"[:10] ; done


5
bashयदि आप कोई shसमाधान पूछ रहे हैं तो टैग क्यों ?
स्टीफन चेज़लस

जवाबों:


16

इस के रूप में सरल।

(दे घुमा के)

for i in * ; do mv -- "$i" "${i:0:5}" ; done

देखा।

और एडवांस्ड बैश-स्क्रिप्टिंग गाइड ( अध्याय 10। हेरफेर करने वाले वेरिएबल्स ) से एक स्पष्टीकरण , ( NOTEउस मैनुअल में त्रुटियों को उजागर करने के लिए अतिरिक्त इनलाइन के साथ ):

पदार्थ निकालना

${string:position}

अर्क से सबस्ट्रिंग $stringपर $position

यदि $stringपैरामीटर "*" या "@" है, तो यह शुरू होने पर स्थितीय मापदंडों को निकालता है $position

${string:position:length}

अर्क $lengthसे सबस्ट्रिंग के पात्रों $stringपर $position

NOTEपैरामीटर विस्तार के आसपास लापता उद्धरण! echoमनमाना डेटा के लिए उपयोग नहीं किया जाना चाहिए।

stringZ=abcABC123ABCabc
#       0123456789.....
#       0-based indexing.

echo ${stringZ:0}                       # abcABC123ABCabc
echo ${stringZ:1}                       # bcABC123ABCabc
echo ${stringZ:7}                       # 23ABCabc 

echo ${stringZ:7:3}                     # 23A
                                        # Three characters of substring.


# Is it possible to index from the right end of the string?

echo ${stringZ:-4}                      # abcABC123ABCabc
# Defaults to full string, as in ${parameter:-default}.
# However . . . 

echo ${stringZ:(-4)}                    # Cabc
echo ${stringZ: -4}                     # Cabc
# Now, it works.
# Parentheses or added space "escape" the position parameter.

स्थिति और लंबाई तर्क "parameterized," किया जा सकता है यह है कि, का प्रतिनिधित्व एक चर के रूप में, बल्कि एक संख्यात्मक निरंतर रूप से।


यदि $stringपैरामीटर "*" या "@" है, तो यह $lengthशुरू होने पर अधिकतम स्थितीय पैरामीटर निकालता है $position

echo ${*:2}          # Echoes second and following positional parameters.
echo ${@:2}          # Same as above.

echo ${*:2:3}        # Echoes three positional parameters, starting at second.

NOTE: expr substrएक GNU एक्सटेंशन है।

expr substr $string $position $length

शुरू $lengthसे ही पात्रों को निकालता है ।$string$position

stringZ=abcABC123ABCabc
#       123456789......
#       1-based indexing.

echo `expr substr $stringZ 1 2`           # ab
echo `expr substr $stringZ 4 3`           # ABC

NOTE: यह echoबेमानी है और इसे और भी कम विश्वसनीय बनाता है। का उपयोग करें expr substr + "$string1" 1 2

NOTE: exprयदि आउटपुट 0 (या -0, 00 ...) है तो एक गैर-शून्य निकास स्थिति के साथ वापस आ जाएगा।


Btw। पुस्तक आधिकारिक उबंटू भंडार में मौजूद है abs-guide


"स्थिति" कहना थोड़ा भ्रामक है क्योंकि यह वास्तव में एक ऑफसेट है, जिसका अर्थ है कि "1 स्थिति" से ${var:1}मूल्य वापस नहीं करता है var, लेकिन वास्तव में 2 से।
Kusalananda

यह सच है, लेकिन जब तक आप सहमत नहीं होंगे तब तक शून्य-शून्य स्थिति हो सकती है। मेरे लिए कौन ठीक है।

9

POSIX में sh,

  • "${var%?????}"$varपिछले 5 अनुगामी पात्रों से छीन लिया गया है (या $varयदि $var5 से कम वर्ण हैं)

  • "${var%"${var#??????????}"}"का पहला 10 अक्षर है $var

  • "${var%_*}"( -> ) के अंत $varमें मिलने वाले सबसे छोटे तार को छीन लिया जाता है ।_*$varfoo_bar_bazfoo_bar
  • "${var%%_*}": कम से कम मैच ( foo_bar_baz-> foo) के बजाय समान लेकिन सबसे लंबा मैच ।
  • यदि आप प्राप्त करना चाहता था foo_bar_: "${var%"${var##*_}"}"( ${var##pattern}रूप में ही है ${var%%pattern}, लेकिन की शुरुआत में पैटर्न की तलाश में $varअंत के बजाय)।

के साथ zsh:

  • $var[1,-6] अंत से 6 वें के लिए पहले चरित्र के लिए (इसलिए सभी लेकिन अंतिम 5)।
  • $var[1,10] पहले 10 पात्रों के लिए।

के साथ ksh, bashया zsh:

  • "${var:0:10}": के पहले 10 अक्षर $var

के साथ bashया zsh:

  • "${var:0:-5}": सभी लेकिन अंतिम 5 वर्ण (एक त्रुटि देता है और यदि $varसेट है तो स्क्रिप्ट से बाहर निकलता है लेकिन 5 वर्णों से कम होता है, वह भी जब $varसेट नहीं किया जाता है zsh)।

यदि आपको बॉर्न shसंगतता की आवश्यकता है , तो मज़बूती से करना बहुत मुश्किल है। यदि आप गारंटी दे सकते हैं कि परिणाम आपके द्वारा किए जा सकने वाले नए वर्णों में समाप्त नहीं होंगे:

first_10=`expr " $var" : ' \(.{1,10\}\)'` # beware the exit status
                                          # may be non-zero if the
                                          # result is 0 or 0000000000

all_but_last_5=`expr " $var" : ' \(.*\).\{5\}'`

आपकी लंबाई $var(सिस्टम के बीच बदलती) पर भी एक सीमा होगी ।

उन सभी समाधानों में, यदि $varबाइट्स शामिल हैं जो वैध वर्णों का हिस्सा नहीं बन सकते हैं, YMMV।


मेरी, वे वास्तव में उन ब्रेसिज़ के अंदर कुछ बदसूरत वाक्य रचना के साथ आए।
बिल्ली

2

shएक स्ट्रिंग से बाहर निकलने का एक अंतर्निहित तरीका प्रदान नहीं करता है (जहां तक ​​मैं देख सकता हूं), लेकिन आपके साथ bashहो सकता है

${i:0:10}

यह आपको चर के मूल्य के पहले दस अक्षर देगा i

सामान्य प्रारूप है ${variable:offset:length}


2

अधिकांश गोले कुछ प्रकार के पैरामीटर विस्तार का समर्थन करते हैं जो आपकी सहायता कर सकते हैं। बैश में, आप उपयोग कर सकते हैं

substr=${string:4:5} # start at position 4, length 5.

में dash, ऑफ़सेट समर्थित नहीं हैं, लेकिन आप अग्रणी और अनुगामी पैटर्न का उपयोग कर सकते हैं:

remove_first3=${string#???}
remove_last2=${string%??}

0

सबसे पहले, forफ़ाइल नामों के लिए लूप का उपयोग न करें ।

फिर, इस तरह से कुछ मदद करनी चाहिए।

find ./ -type f | while read filename ;do
  newfilename=$(echo ${filename}|cut -c 1-10)
  mv ${filename} ${newfilename}
done

3
forफ़ाइल नामों के साथ उपयोग करना बुरा क्यों है ?
कोरोबा

अपने चर का उपयोग करें और printfसुरक्षित होने के लिए उपयोग करें। ... और read -r
Kusalananda

3
ओपी का forलूप गायब होने के अलावा शायद ठीक था --। मैं आपके कोड की 4 पंक्तियों में कम से कम 10 बग देख सकता हूं! जिनमें से कई अच्छी तरह से ज्ञात बुरे अभ्यास जैसे कि फ़ाइल नाम एकल पंक्ति हैं, गूंज का उपयोग करें, लापता उद्धरण
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.