बैश में एक स्ट्रिंग से अंतिम एन अक्षर कैसे निकालें?


202

मेरे पास एक varबैश स्क्रिप्ट है जिसमें एक स्ट्रिंग है, जैसे कि:

echo $var
"some string.rtf"

मैं इस स्ट्रिंग के अंतिम 4 वर्णों को निकालना चाहता हूं और परिणाम को एक नए चर में निर्दिष्ट करना चाहता हूं var2, ताकि

echo $var2
"some string"

मैं यह कैसे कर सकता हूँ?


जवाबों:


15

सबसे पहले, आपको स्पष्ट होना चाहिए कि आप क्या चाहते हैं। यदि आप जानते हैं कि स्ट्रिंग समाप्त होती है .rtfऔर आप इसे हटाना चाहते हैं .rtf, तो आप उपयोग कर सकते हैं var2=${var%.rtf}। यदि आपको पता नहीं है कि प्रत्यय क्या है, लेकिन आप आखिरी से शुरू होने वाली हर चीज को हटाना चाहते हैं ., तो आप उपयोग कर सकते हैं var2=${var%.*}। यदि आप केवल सब कुछ पहले तक रखना चाहते हैं ., तो आप उपयोग कर सकते हैं var2=${var%%.*}। पिछले दो विकल्पों का एक ही परिणाम है यदि केवल एक ही अवधि है, लेकिन अगर एक से अधिक हो सकते हैं, तो आपको यह तय करना चाहिए कि आप क्या चाहते हैं।

यदि आप वास्तव में हमेशा सटीक संख्या निकालना चाहते हैं, तो यहां कुछ विकल्प दिए गए हैं।

आपने बैश को विशेष रूप से निर्दिष्ट किया है, इसलिए हम बैश बिल्डिंग्स के साथ शुरू करेंगे। जिसने सबसे लंबे समय तक काम किया है वह वही प्रत्यय-हटाने वाला सिंटैक्स है जिसका मैंने ऊपर उपयोग किया है: चार वर्णों को हटाने के लिए, उपयोग करें var2=${var%????}। आपको हटाए गए चरित्र के प्रति एक प्रश्न चिह्न की आवश्यकता है, इसलिए यह बड़े सबस्ट्रिंग लंबाई के लिए अस्पष्ट है।

थोड़ा नया है घटिया निष्कर्षण var2=${var::${#var}-4}:। यहां आप 4अलग-अलग वर्णों को निकालने के लिए किसी भी संख्या को रख सकते हैं । ( ${#var}इसे स्ट्रिंग की लंबाई से बदल दिया जाता है, इसलिए यह वास्तव में पहला (लंबाई - 4) अक्षर रखने के लिए कह रहा है।)

बैश के नए संस्करण (विशेष रूप से 4+, जिसका अर्थ है कि जो MacOS के साथ काम नहीं करेगा) आपको बस इसे सरल बनाने की अनुमति देता है var2=${var::-4}

यदि आप वास्तव में बैश का उपयोग नहीं कर रहे हैं, लेकिन कुछ अन्य POSIX- प्रकार शेल, प्रत्यय हटाने अभी भी काम करेंगे, यहां तक ​​कि सादे पुराने डैश में (जहां बाकी कोई भी नहीं होगा)। Zsh में, वे सभी काम करते हैं, लेकिन आपको कॉलोनों के 0बीच रखना होगा : var2=${var:0:-4}आदि। ksh में, आपको 0 की आवश्यकता है और स्पष्ट लंबाई -4 अभिव्यक्ति का उपयोग करना होगा var2=${var:0:${#var}-4}:।

आप बेशक उपयोगिता कार्यक्रम की मदद से इसे करने के लिए कमांड प्रतिस्थापन का उपयोग कर सकते हैं; वहाँ बहुत सारे हैं जो काम करेंगे, लेकिन कुछ ऐसा है जो var2=$(cut -c -4 <<<"$var")शायद सबसे छोटा विकल्प है।


240

आप इस तरह कर सकते हैं:

#!/bin/bash

v="some string.rtf"

v2=${v::-4}

echo "$v --> $v2"

9
बैश 4+ मुझे लगता है।
इटन रिस्नर

69
यह bash4+ है, लेकिन पहले के संस्करण में आप थोड़ा अधिक समय तक उपयोग कर सकते हैं ${v::${#v}-4}
चेपनर

8
मेरे लिए काम नहीं किया, बैश कहते हैं '' बुरा प्रतिस्थापन '
इवान मारजानोविक

15
किसी कारण से, zsh ${v::-4}croaks में "zsh: समापन ब्रेस अपेक्षित"। लेकिन नीचे @fredtantini का जवाब ${v:0:-4}ठीक काम करता है।
पियरे डी

6
त्रुटि के साथ: -2: एक्सप्रेशन एक्सप्रेशन <0
एडवर्ड

172

स्ट्रिंग उपयोग के अंत से चार वर्णों को निकालने के लिए ${var%????}

अंतिम .उपयोग के बाद सब कुछ निकालने के लिए ${var%.*}


12
शुद्ध शेल उत्तर, और BASH 3.x में काम करेगा जो कई प्रणालियों पर पाया जाता है जिन्होंने लाइसेंस मुद्दों के कारण BASH 4.x को लागू करने से इनकार कर दिया है।
डेविड डब्ल्यू।

1
यह छोटा है क्योंकि यह छोटे तारों को प्राप्त करने के खिलाफ मजबूत है; इंडेक्स ऑफ़सेट वेरिएंट तब विफल हो जाता है।
राफेल

बैश 3.2.25 में काम करता है - सबसे अच्छा संभव जवाब - बस क्या मैं खोज रहा था
capser

बहुत बढ़िया जवाब। कैसे स्ट्रिंग के सामने एक हटाने के बारे में?
15:20 बजे user2023370

3
@ user2023370 प्रलेखन से पता चलता है कि इसके लिए एक संगत पैरामीटर प्रतिस्थापन ${var#????}है।
ट्रिपल जूल

48

मेरे लिए क्या काम था:

echo "hello world" | rev | cut -c5- | rev
# hello w

लेकिन मैंने इसे एक फाइल में लाइनों को ट्रिम करने के लिए इस्तेमाल किया है, इसलिए यह अजीब लग रहा है। वास्तविक उपयोग था:

cat somefile | rev | cut -c5- | rev

cutकेवल आपको कुछ प्रारंभिक स्थिति से ट्रिमिंग के रूप में प्राप्त होता है, जो कि अगर आपको चर लंबाई की पंक्तियों की आवश्यकता होती है, तो यह बुरा है। तो यह समाधान उलटा ( rev) स्ट्रिंग और अब हम इसकी समाप्ति स्थिति से संबंधित है, फिर cutउल्लेख के रूप में उपयोग करता है , और फिर से (फिर से rev) , इसे वापस मूल क्रम में ले जाता है।


यह सही नहीं है और जो पूछा जा रहा है उसका जवाब नहीं है। revलाइनों को उलट देता है, तार नहीं। echo $SOME_VAR | rev | ...शायद व्यवहार नहीं करेगा कि कोई कैसे उम्मीद करेगा।
मोहम्मद नासिरिफ़र

2
वजह से @Mohammad के हवाले से टूट, कि है एक ही पंक्ति।
ट्रिपल जूल

38

परिवर्तनीय विस्तार / प्रतिस्थापन प्रतिस्थापन का उपयोग करना :

$ {Var /% पैटर्न / प्रतिस्थापन}

यदि var मिलान पैटर्न का प्रत्यय है, तो पैटर्न के लिए प्रतिस्थापन प्रतिस्थापित करें।

तो आप कर सकते हैं:

~$ echo ${var/%????/}
some string

वैकल्पिक रूप से,

यदि आपके पास हमेशा एक ही 4 अक्षर हैं

~$ echo ${var/.rtf/}
some string

यदि यह हमेशा समाप्त होता है .xyz:

~$ echo ${var%.*}
some string

आप स्ट्रिंग की लंबाई का भी उपयोग कर सकते हैं:

~$ len=${#var}
~$ echo ${var::len-4}
some string

या केवल echo ${var::-4}


len=${#var}; echo ${var::len-4}को छोटा किया जा सकता है echo ${var:0:-4}:-) EDIT: या जैसा कि @iyonizer ने बताया, बस echo ${var::-4}...
aishsane

26

आप sed का उपयोग कर सकते हैं,

sed 's/.\{4\}$//' <<< "$var"

उदाहरण:

$ var="some string.rtf"
$ var1=$(sed 's/.\{4\}$//' <<< "$var")
$ echo $var1
some string

1
और मैं परिणाम को कैसे बताऊं var2?
बेको डि

यह अच्छा है क्योंकि यह इस तरह एक लाइन पर काम करता है ... | sed 's /। \ {4 \} $ //'। चर का उपयोग किए बिना किया जा सकता है
सैम

3

मैंने निम्नलिखित कोशिश की और यह मेरे लिए काम किया:

#! /bin/bash

var="hello.c"
length=${#var}
endindex=$(expr $length - 4)
echo ${var:0:$endindex}

आउटपुट: hel


1

आशा है कि नीचे दिए गए उदाहरण से मदद मिलेगी,

echo ${name:0:$((${#name}-10))} -> ${name:start:len}

  • उपरोक्त कमांड में, नाम परिवर्तनशील है।
  • start स्ट्रिंग प्रारंभिक बिंदु है
  • len स्ट्रिंग की लंबाई है जिसे हटाया जाना है।

उदाहरण:

    read -p "Enter:" name
    echo ${name:0:$((${#name}-10))}

आउटपुट:

    Enter:Siddharth Murugan
    Siddhar

नोट: बैश 4.2 ने नकारात्मक विकल्प के लिए समर्थन जोड़ा


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

0

यह मेरे लिए स्ट्रिंग के आकार की गणना करके काम करता है।
यह आसान है कि आपको उस मूल्य को प्रतिध्वनित करने की आवश्यकता है जिसे आपको वापस करने की आवश्यकता है और फिर इसे नीचे की तरह संग्रहीत करें

removechars(){
        var="some string.rtf"
        size=${#var}
        echo ${var:0:size-4}  
    }
    removechars
    var2=$?

कुछ तार


0

इस मामले में आप आधारभूत का उपयोग कर सकते हैं यह मानते हुए कि आपके पास उन फ़ाइलों पर समान प्रत्यय है जिन्हें आप हटाना चाहते हैं।

उदाहरण:

basename -s .rtf "some string.rtf"

यह "कुछ स्ट्रिंग" लौटाएगा

यदि आप प्रत्यय नहीं जानते हैं, और यह चाहते हैं कि अंतिम डॉट सहित सभी चीजों को हटा दें:

f=file.whateverthisis
basename "${f%.*}"

आउटपुट "फ़ाइल"

% का मतलब है चॉप,। आप क्या काट रहे हैं, * वाइल्डकार्ड है

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