शेल स्क्रिप्ट में स्ट्रिंग हेरफेर का उपयोग करके एक स्ट्रिंग के अंतिम चरित्र को हटा दें


187

मैं एक स्ट्रिंग के अंतिम चरित्र को हटाना चाहूंगा, मैंने इस छोटी स्क्रिप्ट की कोशिश की:

#! /bin/sh 

t="lkj"
t=${t:-2}
echo $t

लेकिन यह "lkj" प्रिंट करता है, मैं क्या गलत कर रहा हूं?

जवाबों:


115

POSIX शेल में, वाक्यविन्यास का ${t:-2}अर्थ कुछ अलग होता है - यह tअगर tसेट किया गया है और गैर अशक्त है, और अन्यथा मूल्य के मूल्य तक फैलता है 2। पैरामीटर विस्तार द्वारा किसी एकल वर्ण को ट्रिम करने के लिए, आप जो सिंटैक्स चाहते हैं, वह है${t%?}

ध्यान दें कि ksh93, bashया zsh, ( ${t:(-2)}या ${t: -2}स्थान पर ध्यान दें) एक विकल्प विस्तार के रूप में कानूनी हैं, लेकिन शायद आप जो चाहते हैं, वे नहीं हैं, क्योंकि वे अंत से शुरू करने वाले प्रतिस्थापन अक्षर को अंत से वापस लौटाते हैं (अर्थात यह पहले वर्ण को हटाता iहै स्ट्रिंग ijk)।

अधिक जानकारी के लिए बैश संदर्भ मैनुअल के शेल पैरामीटर विस्तार खंड देखें:


4
क्या आप यह समझाने की परवाह करेंगे कि '%' के पीछे क्या जादू है? ?
afraisse

8
@afraisse ${parameter%word}सबसे छोटे प्रत्यय पैटर्न को हटाता wordहैman bash
व्यास

3
यह बैश के लिए अच्छी तरह से काम करता है 4.1.2: $ {t%?} सेंटोस / आरएचईएल 6.x के साथ अटके हुए लोगों के लिए
जोय टी

185

साथ bash4.2 और इसके बाद के संस्करण, आप कर सकते हैं:

${var::-1}

उदाहरण:

$ a=123
$ echo "${a::-1}"
12

ध्यान दें कि पुराने के लिए bash(उदाहरण के लिए, bash 3.2.5OS X पर), आपको कॉलन के बीच और बाद में रिक्त स्थान छोड़ना चाहिए:

${var: : -1}

13
यह bashसंस्करण 4.2-अल्फा और इसके बाद के संस्करण के लिए काम करता है, मेरे पास जिस संस्करण तक पहुंच है वह बहुत बुरा है। : - /
hjk

2
@ वियाज़िज़: बैश चैंज से, नकारात्मक लंबाई को ${var:offset:lenght}केवल में जोड़ा गया था bash 4.2। हो सकता है OSX इसके लिए अपना खुद का पैच जोड़े bash
कोउंगलम

1
@cuonglm न तो काम करते हैं: /
iamaziz

1
मैक पर काम नहीं करता है।
शिंज़ौ

1
मैकस्टर्स, रस के जवाब के लिए नीचे देखो
पी i

67

अंतिम nवर्णों को एक पंक्ति से निकालने के लिए जो sedOR का उपयोग नहीं करता है 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

61

सेड का उपयोग करना उतना ही तेज होना चाहिए

sed 's/.$//'

आपकी एकल गूँज तब है echo ljk | sed 's/.$//'
इसका उपयोग करके, 1-लाइन स्ट्रिंग किसी भी आकार का हो सकता है।


10
ध्यान दें कि सामान्य स्थिति में, यह स्ट्रिंग के अंतिम वर्ण को नहीं हटाता है , लेकिन स्ट्रिंग की प्रत्येक पंक्ति का अंतिम वर्ण है
स्टीफन चेज़लस

44

शेल के आधार पर कुछ विकल्प:

  • POSIX: t=${t%?}
  • बॉर्न: t=`expr " $t" : ' \(.*\).'`
  • zsh / यश: t=${t[1,-2]}
  • बैश / zsh: t=${t:0:-1}
  • ksh93 / bash / zsh / mksh: t=${t:0:${#t}-1}
  • ksh93 / bash / zsh / mksh: t=${t/%?}
  • ksh93: t=${t/~(E).$/}
  • es: @ {t=$1} ~~ $t *?

ध्यान दें कि जब सभी अंतिम चरित्र को छीनने वाले होते हैं , तो आप पाएंगे कि कुछ कार्यान्वयन (जो मल्टी-बाइट वर्ण का समर्थन नहीं करते हैं) इसके बजाय अंतिम बाइट को छीन लेते हैं (इसलिए बहु-बाइट होने पर अंतिम वर्ण को भ्रष्ट कर देगा। )।

exprसंस्करण मान लिया गया $tएक से अधिक न्यू लाइन चरित्र में खत्म नहीं होता। यदि परिणामी स्ट्रिंग समाप्त हो रही है 0(या कुछ कार्यान्वयन के साथ 000भी -0) तो यह गैर-शून्य निकास स्थिति भी लौटाएगा । यदि स्ट्रिंग में अमान्य वर्ण हैं, तो यह अप्रत्याशित परिणाम भी दे सकता है।


अच्छा और पूरी तरह से! लेकिन ... मुझे लगता है कि उन सभी गोले POSIX का समर्थन करते हैं, इसलिए सभी को बस उस एक का उपयोग करना चाहिए जो सबसे अधिक पोर्टेबल हो। सबसे छोटा चरित्र गिनती, भी!
रस

@ रॉस, t=${t%?}बॉर्न नहीं है , लेकिन आजकल एक बॉर्न शेल में आने की संभावना नहीं है। ${t%?}हालांकि अन्य सभी में काम करता है।
स्टीफन चेजलस

मछली के खोल का कोई विकल्प नहीं दिया गया! संभवतः ksh93 की तुलना में इन दिनों अधिक लोकप्रिय ...
rien333

@ rien333। मैं इंटरफ़ेस को थोड़ा स्थिर करने की प्रतीक्षा करूँगा। fishकार्य प्रगति पर है। २.३.० जिसने बिलिन को पेश किया stringथा, वह प्रश्नोत्तर के समय जारी नहीं किया गया था। जिस संस्करण पर मैं इसका परीक्षण कर रहा हूं, आपको उसकी आवश्यकता है string replace -r '(?s).\z' '' -- $t(और मुझे उम्मीद है कि वे इसे बदलना चाहेंगे, उन्हें पीसीआर में उत्तीर्ण होने वाले झंडे को बदलना चाहिए) या अधिक जटिल। यह न्यूलाइन वर्णों के साथ खराब व्यवहार करता है, और मुझे पता है कि वे इसे बदलने की योजना बना रहे हैं।
स्टीफन चेज़लस

POSIX उत्तर के लिए अपग्रेड किया गया। बैश ३.२.५ ((१) पर काम करने की पुष्टि की
अविन्द्र गोलचरण ५'१ 20:

26

सबसे पोर्टेबल, और सबसे छोटा, उत्तर लगभग निश्चित रूप से है:

${t%?}

यह bash, sh, ash, dash, busybox / ash, zsh, ksh, आदि में काम करता है।

यह पुराने स्कूल शेल पैरामीटर विस्तार का उपयोग करके काम करता है। विशेष रूप से, %पैरामीटर के सबसे छोटे मिलान प्रत्यय को हटाने के लिए निर्दिष्ट करता है tजो ग्लोब पैटर्न ?(यानी: किसी भी वर्ण) से मेल खाता है ।

(अधिक) अधिक विस्तृत विवरण और अधिक पृष्ठभूमि के लिए यहां "सबसे छोटा प्रत्यय पैटर्न निकालें" देखें । man bash"पैरामीटर विस्तार" के तहत अपने शेल (उदाहरण के लिए ) के लिए डॉक्स भी देखें ।


एक साइड नोट के रूप में, यदि आप इसके बजाय पहले वर्ण को निकालना चाहते थे, तो आप उपयोग करेंगे ${t#?}, क्योंकि #पीछे (प्रत्यय) के बजाय स्ट्रिंग (उपसर्ग) के सामने से मिलान होता है।

यह भी ध्यान देने योग्य है कि दोनों %और #हैं %%और ##संस्करण, जो दिए गए पैटर्न के सबसे लंबे संस्करण को सबसे कम के बजाय मेल खाते हैं । दोनों ${t%%?}और ${t##?}इस मामले में उनके एक ऑपरेटर के रूप में भी ऐसा ही होता है, हालांकि (ताकि बेकार अतिरिक्त चरित्र न जोड़ें)। ऐसा इसलिए है क्योंकि दिए गए ?पैटर्न केवल एक ही चरित्र से मेल खाते हैं। *कुछ गैर-वाइल्डकार्ड के साथ मिक्स और चीजों के साथ %%और अधिक दिलचस्प मिलता है और ##

पैरामीटर विस्तार को समझना, या कम से कम उनके अस्तित्व के बारे में जानना और उन्हें कैसे देखना है, यह जानने के लिए, कई स्वादों के शेल स्क्रिप्ट को लिखने और डिक्रिप करने के लिए अविश्वसनीय रूप से उपयोगी है। पैरामीटर विस्तार अक्सर कई लोगों के लिए रहस्यमय खोल वूडू की तरह लग रही है क्योंकि ... ठीक है ... वे कर रहे हैं रहस्यमय खोल वूडू (हालांकि बहुत अच्छी तरह से प्रलेखित यदि आप "पैरामीटर विस्तार" देखने के लिए जानते हैं)। जब आप एक शेल में फंस जाते हैं, तो टूल बेल्ट में निश्चित रूप से अच्छा होता है।


लघु और मधुर, और MacOS और Linux दोनों पर काम करता है!
डबर्नार्ड

18
t=lkj
echo ${t:0:${#t}-1}

आपको 0 से स्ट्रिंग लंबाई -1 का एक विकल्प मिलता है। ध्यान दें कि यह स्थानान्तरण विशिष्ट है, और अन्य गोले पर काम नहीं करेगा।

उदाहरण के लिए, dashयहां तक ​​कि पार्स करने में भी सक्षम नहीं है

echo ${t:0:$(expr ${#t} - 1)}

उदाहरण के लिए, उबंटू पर, /bin/shहैdash


15

आप headसभी लेकिन अंतिम चरित्र का प्रिंट आउट लेने के लिए भी उपयोग कर सकते हैं ।

$ s='i am a string'
$ news=$(echo -n $s | head -c -1)
$ echo $news
i am a strin

लेकिन दुर्भाग्य से कुछ संस्करणों में headअग्रणी -विकल्प शामिल नहीं है। यह उस मामले के लिए है headजो ओएस एक्स के साथ आता है।


5

नियमित अभिव्यक्ति का उपयोग करना काफी आसान है:

n=2
echo "lkj" | sed "s/\(.*\).\{$n\}/\1/"

5

कुछ शोधन। एक से अधिक वर्णों को निकालने के लिए, आप कई प्रश्न चिह्न जोड़ सकते हैं। उदाहरण के लिए, चर से अंतिम दो वर्णों को हटाने के लिए: $SRC_IP_MSGआप उपयोग कर सकते हैं:

SRC_IP_MSG=${SRC_IP_MSG%??}

4

शुद्ध बैश के कुछ संभावित उपयोगों को पूरा करने के लिए:

#!/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 नाम दिया गया है)


1

जैसा कि हम कमांड लाइन, या शेल स्क्रिप्ट में भी php का उपयोग कर सकते हैं । यह कभी-कभी सर्जिकल पार्सिंग के लिए उपयोगी होता है।

php -r "echo substr('Hello', 0, -1);" 
// Output hell

पाइपिंग के साथ:

echo "hello" | php -r "echo substr(trim(fgets(STDIN)), 0, -1);"
// Output hell

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