मैं एक स्ट्रिंग के अंतिम चरित्र को हटाना चाहूंगा, मैंने इस छोटी स्क्रिप्ट की कोशिश की:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
लेकिन यह "lkj" प्रिंट करता है, मैं क्या गलत कर रहा हूं?
मैं एक स्ट्रिंग के अंतिम चरित्र को हटाना चाहूंगा, मैंने इस छोटी स्क्रिप्ट की कोशिश की:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
लेकिन यह "lkj" प्रिंट करता है, मैं क्या गलत कर रहा हूं?
जवाबों:
POSIX शेल में, वाक्यविन्यास का ${t:-2}
अर्थ कुछ अलग होता है - यह t
अगर t
सेट किया गया है और गैर अशक्त है, और अन्यथा मूल्य के मूल्य तक फैलता है 2
। पैरामीटर विस्तार द्वारा किसी एकल वर्ण को ट्रिम करने के लिए, आप जो सिंटैक्स चाहते हैं, वह है${t%?}
ध्यान दें कि ksh93
, bash
या zsh
, ( ${t:(-2)}
या ${t: -2}
स्थान पर ध्यान दें) एक विकल्प विस्तार के रूप में कानूनी हैं, लेकिन शायद आप जो चाहते हैं, वे नहीं हैं, क्योंकि वे अंत से शुरू करने वाले प्रतिस्थापन अक्षर को अंत से वापस लौटाते हैं (अर्थात यह पहले वर्ण को हटाता i
है स्ट्रिंग ijk
)।
अधिक जानकारी के लिए बैश संदर्भ मैनुअल के शेल पैरामीटर विस्तार खंड देखें:
${parameter%word}
सबसे छोटे प्रत्यय पैटर्न को हटाता word
हैman bash
साथ bash
4.2 और इसके बाद के संस्करण, आप कर सकते हैं:
${var::-1}
उदाहरण:
$ a=123
$ echo "${a::-1}"
12
ध्यान दें कि पुराने के लिए bash
(उदाहरण के लिए, bash 3.2.5
OS X पर), आपको कॉलन के बीच और बाद में रिक्त स्थान छोड़ना चाहिए:
${var: : -1}
bash
संस्करण 4.2-अल्फा और इसके बाद के संस्करण के लिए काम करता है, मेरे पास जिस संस्करण तक पहुंच है वह बहुत बुरा है। : - /
${var:offset:lenght}
केवल में जोड़ा गया था bash 4.2
। हो सकता है OSX इसके लिए अपना खुद का पैच जोड़े bash
।
अंतिम n
वर्णों को एक पंक्ति से निकालने के लिए जो sed
OR का उपयोग नहीं करता है awk
:
> echo lkj | rev | cut -c (n+1)- | rev
इसलिए उदाहरण के लिए आप इसका one character
उपयोग करके अंतिम वर्ण को हटा सकते हैं :
> echo lkj | rev | cut -c 2- | rev
> lk
से rev
मैनपेज:
वर्णन
: संशोधित उपयोगिता मानक आउटपुट में निर्दिष्ट फ़ाइलों को कॉपी करती है, हर पंक्ति में वर्णों के क्रम को उलट देती है। यदि कोई फ़ाइल विशिष्ट नहीं हैं, तो मानक इनपुट पढ़ा जाता है।
अपडेट करें:
यदि आप स्ट्रिंग की लंबाई नहीं जानते हैं, तो कोशिश करें:
$ x="lkj"
$ echo "${x%?}"
lk
सेड का उपयोग करना उतना ही तेज होना चाहिए
sed 's/.$//'
आपकी एकल गूँज तब है echo ljk | sed 's/.$//'
।
इसका उपयोग करके, 1-लाइन स्ट्रिंग किसी भी आकार का हो सकता है।
शेल के आधार पर कुछ विकल्प:
t=${t%?}
t=`expr " $t" : ' \(.*\).'`
t=${t[1,-2]}
t=${t:0:-1}
t=${t:0:${#t}-1}
t=${t/%?}
t=${t/~(E).$/}
@ {t=$1} ~~ $t *?
ध्यान दें कि जब सभी अंतिम चरित्र को छीनने वाले होते हैं , तो आप पाएंगे कि कुछ कार्यान्वयन (जो मल्टी-बाइट वर्ण का समर्थन नहीं करते हैं) इसके बजाय अंतिम बाइट को छीन लेते हैं (इसलिए बहु-बाइट होने पर अंतिम वर्ण को भ्रष्ट कर देगा। )।
expr
संस्करण मान लिया गया $t
एक से अधिक न्यू लाइन चरित्र में खत्म नहीं होता। यदि परिणामी स्ट्रिंग समाप्त हो रही है 0
(या कुछ कार्यान्वयन के साथ 000
भी -0
) तो यह गैर-शून्य निकास स्थिति भी लौटाएगा । यदि स्ट्रिंग में अमान्य वर्ण हैं, तो यह अप्रत्याशित परिणाम भी दे सकता है।
t=${t%?}
बॉर्न नहीं है , लेकिन आजकल एक बॉर्न शेल में आने की संभावना नहीं है। ${t%?}
हालांकि अन्य सभी में काम करता है।
fish
कार्य प्रगति पर है। २.३.० जिसने बिलिन को पेश किया string
था, वह प्रश्नोत्तर के समय जारी नहीं किया गया था। जिस संस्करण पर मैं इसका परीक्षण कर रहा हूं, आपको उसकी आवश्यकता है string replace -r '(?s).\z' '' -- $t
(और मुझे उम्मीद है कि वे इसे बदलना चाहेंगे, उन्हें पीसीआर में उत्तीर्ण होने वाले झंडे को बदलना चाहिए) या अधिक जटिल। यह न्यूलाइन वर्णों के साथ खराब व्यवहार करता है, और मुझे पता है कि वे इसे बदलने की योजना बना रहे हैं।
सबसे पोर्टेबल, और सबसे छोटा, उत्तर लगभग निश्चित रूप से है:
${t%?}
यह bash, sh, ash, dash, busybox / ash, zsh, ksh, आदि में काम करता है।
यह पुराने स्कूल शेल पैरामीटर विस्तार का उपयोग करके काम करता है। विशेष रूप से, %
पैरामीटर के सबसे छोटे मिलान प्रत्यय को हटाने के लिए निर्दिष्ट करता है t
जो ग्लोब पैटर्न ?
(यानी: किसी भी वर्ण) से मेल खाता है ।
(अधिक) अधिक विस्तृत विवरण और अधिक पृष्ठभूमि के लिए यहां "सबसे छोटा प्रत्यय पैटर्न निकालें" देखें । man bash
"पैरामीटर विस्तार" के तहत अपने शेल (उदाहरण के लिए ) के लिए डॉक्स भी देखें ।
एक साइड नोट के रूप में, यदि आप इसके बजाय पहले वर्ण को निकालना चाहते थे, तो आप उपयोग करेंगे ${t#?}
, क्योंकि #
पीछे (प्रत्यय) के बजाय स्ट्रिंग (उपसर्ग) के सामने से मिलान होता है।
यह भी ध्यान देने योग्य है कि दोनों %
और #
हैं %%
और ##
संस्करण, जो दिए गए पैटर्न के सबसे लंबे संस्करण को सबसे कम के बजाय मेल खाते हैं । दोनों ${t%%?}
और ${t##?}
इस मामले में उनके एक ऑपरेटर के रूप में भी ऐसा ही होता है, हालांकि (ताकि बेकार अतिरिक्त चरित्र न जोड़ें)। ऐसा इसलिए है क्योंकि दिए गए ?
पैटर्न केवल एक ही चरित्र से मेल खाते हैं। *
कुछ गैर-वाइल्डकार्ड के साथ मिक्स और चीजों के साथ %%
और अधिक दिलचस्प मिलता है और ##
।
पैरामीटर विस्तार को समझना, या कम से कम उनके अस्तित्व के बारे में जानना और उन्हें कैसे देखना है, यह जानने के लिए, कई स्वादों के शेल स्क्रिप्ट को लिखने और डिक्रिप करने के लिए अविश्वसनीय रूप से उपयोगी है। पैरामीटर विस्तार अक्सर कई लोगों के लिए रहस्यमय खोल वूडू की तरह लग रही है क्योंकि ... ठीक है ... वे कर रहे हैं रहस्यमय खोल वूडू (हालांकि बहुत अच्छी तरह से प्रलेखित यदि आप "पैरामीटर विस्तार" देखने के लिए जानते हैं)। जब आप एक शेल में फंस जाते हैं, तो टूल बेल्ट में निश्चित रूप से अच्छा होता है।
आप head
सभी लेकिन अंतिम चरित्र का प्रिंट आउट लेने के लिए भी उपयोग कर सकते हैं ।
$ s='i am a string'
$ news=$(echo -n $s | head -c -1)
$ echo $news
i am a strin
लेकिन दुर्भाग्य से कुछ संस्करणों में head
अग्रणी -
विकल्प शामिल नहीं है। यह उस मामले के लिए है head
जो ओएस एक्स के साथ आता है।
शुद्ध बैश के कुछ संभावित उपयोगों को पूरा करने के लिए:
#!/bin/bash
# Testing substring removal
STR="Exemple string with trailing whitespace "
echo "'$STR'"
echo "Removed trailing whitespace: '${STR:0:${#STR}-1}'"
echo "Removed trailing whitespace: '${STR/%\ /}'"
पहला सिंटैक्स एक स्ट्रिंग से एक सबस्ट्रिंग लेता है, सिंटैक्स
एक दूसरे के लिए है, साइन पर ध्यान दें , जिसका अर्थ है 'लाइन के अंत से' और सिंटैक्स है
${STRING:OFFSET:LENGTH}
%
${STRING/PATTERN/SUBSTITUTION}
और यहाँ उपर्युक्त दो छोटे रूप हैं
echo "Removed trailing whitespace: '${STR::-1}'"
echo "Removed trailing whitespace: '${STR%\ }'"
यहाँ फिर से %
संकेत पर ध्यान दें , जिसका अर्थ है 'निकालें (जो कि' की जगह ') सबसे छोटा मिलान वाला पैटर्न (यहाँ पर PARAMETER के अंत से बची हुई जगह ' \ ' का प्रतिनिधित्व किया गया है - यहाँ STR नाम दिया गया है)