पहले एक को छोड़कर सभी तर्कों को संसाधित करें (एक बाश स्क्रिप्ट में)


444

मेरे पास एक सरल स्क्रिप्ट है जहां पहला तर्क फ़ाइलनाम के लिए आरक्षित है, और अन्य सभी वैकल्पिक तर्क को स्क्रिप्ट के अन्य भागों में पास किया जाना चाहिए।

Google का उपयोग करके मुझे यह विकी मिला , लेकिन इसने एक शाब्दिक उदाहरण प्रदान किया:

echo "${@: -1}"

मुझे काम करने के लिए कुछ और नहीं मिल सकता है, जैसे:

echo "${@:2}"

या

echo "${@:2,1}"

मुझे टर्मिनल से "खराब प्रतिस्थापन" मिलता है।

समस्या क्या है, और मैं सभी को कैसे संसाधित कर सकता हूं, लेकिन पहला तर्क एक बैश स्क्रिप्ट को दिया गया?


21
किसी और को भ्रमित करने के लिए कॉल करने के लिए, गलत शेबंग को "{@:2}"काम नहीं करने के लिए प्रदान किया गया था , यही कारण है कि ऊपर सही उत्तर मैच करता है।
गुवाँटे

3
आपने बस डिफ़ॉल्ट शेल का उपयोग किया, जो उबंटू और कई अन्य लिनक्स पर डैश है। डैश में "$ {@: -1}" के रूप में व्याख्या की गई है: {पैरामीटर: -word} - डिफ़ॉल्ट मानों का उपयोग करें, और पैरामीटर परिभाषित या शून्य होने पर शब्द का उपयोग करें। तो डैश में "$ {@: -1}" परिणाम "$ @" के समान ही हैं। बैश का उपयोग करने के लिए स्क्रिप्ट फाइल में निम्नलिखित पहली पंक्ति का उपयोग करें: #! / Bin / bash
luart

जवाबों:


660

इसे इस्तेमाल करो:

echo "${@:2}"

निम्नलिखित सिंटैक्स:

echo "${*:2}"

के रूप में अच्छी तरह से काम करेगा, लेकिन अनुशंसित नहीं है, क्योंकि @Gordon पहले से ही समझाया, का उपयोग करते हुए *, यह सभी तर्कों को रिक्त स्थान के साथ एक ही तर्क के रूप में चलाता है, जबकि @उनके बीच के विराम को संरक्षित करता है (भले ही कुछ तर्कों में स्वयं रिक्त स्थान हों )। इससे फर्क नहीं पड़ता है echo, लेकिन यह कई अन्य आदेशों के लिए मायने रखता है।


7
मुझे सिर्फ एहसास हुआ कि मेरा शेबंग खराब था: #!/usr/bin/env shइसीलिए मुझे समस्याएँ थीं। आप उदाहरण के लिए ठीक काम करते हैं, जैसा कि ऊपर प्रदान किया गया है, मैंने उस शबंग को हटा दिया
थीटा

110
"${@:2}"इसके बजाय का उपयोग करें - *रिक्त स्थान के साथ एक ही तर्क के रूप में एक साथ सभी तर्कों का उपयोग करते हुए, @उनके बीच के विराम को संरक्षित करता है (भले ही कुछ तर्कों में रिक्त स्थान हो)। अंतर के साथ ध्यान देने योग्य नहीं है echo, लेकिन यह कई अन्य चीजों के लिए मायने रखता है।
गॉर्डन डेविसन

2
@GordonDavisson यहाँ पूरे बिंदु एक साथ तर्कों को चलाने के लिए है। क्या हम फाइलनाम पास कर रहे थे, आप सही होंगे। echoआपके लिए उन्हें माफ करने के लिए पर्याप्त क्षमा कर रहा है; अन्य कमांड इतनी अच्छी नहीं हो सकती हैं। सिर्फ एक या अन्य उपयोग न करें: के बीच अंतर जानने *और @है, और जब प्रत्येक उपयोग करने के लिए। आपको उनके बारे में समान रूप से उपयोग करना चाहिए। इसका एक अच्छा उदाहरण जब यह एक समस्या होगी: यदि $3एक पंक्ति विराम ( \n) शामिल है, तो इसे एक स्थान के साथ बदल दिया जाएगा, बशर्ते आपके पास एक डिफ़ॉल्ट $IFSचर हो।
ज़ेनेक्सर

1
@Zenexer: जैसा कि मैं इसे समझता हूं, सवाल यह था कि "स्क्रिप्ट के अन्य भाग" के लिए पहला तर्क कैसे पास echoकिया जाए , केवल उदाहरण के रूप में उपयोग किया जाता है - जिस स्थिति में उन्हें एक साथ नहीं चलाया जाना चाहिए । मेरे अनुभव में, जिन स्थितियों में आप चाहते हैं कि वे एक साथ चलते हैं वे दुर्लभ हैं ( एक उदाहरण के लिए इस प्रश्न को देखें ), और "$@"लगभग हमेशा वही होता है जो आप चाहते हैं। साथ ही, लाइन ब्रेक के साथ आपके द्वारा बताई गई समस्या केवल तब होती है यदि $@(या $*) दोहरे उद्धरण में नहीं है।
गॉर्डन डेविसन

@GordonDavisson हम्म ... आप सही कह रहे हैं, अब मैं इसके बारे में सोचता हूं; लाइन ब्रेक एक मुद्दा नहीं होना चाहिए। मैं कुछ और सोच रहा होगा। हालाँकि, मुझे अभी भी उन्हें एक साथ चलाने के बारे में असहमत होना पड़ा है; मुझे $*अपनी लिपियों में अक्सर उपयोग करने की आवश्यकता है ।
ज़ेनेक्सर

180

यदि आप एक समाधान चाहते हैं जो /bin/shकोशिश में भी काम करता है

first_arg="$1"
shift
echo First argument: "$first_arg"
echo Remaining arguments: "$@"

shift [n]स्थितीय मापदंडों को n बार बदलता है । एक shiftसेट के मूल्य $1के मूल्य के $2, के मूल्य $2के मूल्य के $3, और इतने पर, का मूल्य कम हो रही $#एक के बाद।


25
+1: आपको इसे दूर स्थानांतरित करने से पहले शायद $ 1 को एक चर में सहेजना चाहिए।
ग्लेन जैकमैन

3
हैरानी की foo=shiftबात नहीं है कि मैं क्या उम्मीद करूँगा।
कीथ स्माइली

मुझे पता है कि यह पुराना है, लेकिन कोशिश करोfoo=$(shift)
रुमान किदवई

12
@raumaankidwai जो 2 कारणों से काम नहीं करता है: 1) shift(शेल में) का कोई आउटपुट नहीं है। यह सिर्फ डिस्कस करता है $1और सब कुछ नीचे गिरा देता है। 2) $(...)एक उपखंड शुरू करता है, जिसके अपने स्थानीय तर्क हैं। यह उपधारा में तर्कों को बदल देता है, जो माता
बेन जैक्सन

धन्यवाद :) क्या somecommand "$1" "${@:2}"इस विधि के साथ क्या करने का कोई तरीका है (अर्थात "इनलाइन" शिफ्ट) हालांकि?
बेनामी


0

यह कुछ और की तलाश में आया था। जबकि पोस्ट काफी पुरानी लग रही है, बैश में सबसे आसान समाधान नीचे सचित्र है (कम से कम 4 बैश) set -- "${@:#}"जहां # का उपयोग करते हुए सरणी तत्व की शुरुआती संख्या हम आगे संरक्षित करना चाहते हैं:

    #!/bin/bash

    someVar="${1}"
    someOtherVar="${2}"
    set -- "${@:3}"
    input=${@}

    [[ "${input[*],,}" == *"someword"* ]] && someNewVar="trigger"

    echo -e "${someVar}\n${someOtherVar}\n${someNewVar}\n\n${@}"

असल में, set -- "${@:3}"बस पर्ल के शिफ्ट की तरह सरणी में पहले दो तत्वों को बंद कर देता है और तीसरे सहित सभी शेष तत्वों को संरक्षित करता है। मुझे संदेह है कि आखिरी तत्वों को भी बंद करने का एक तरीका है।

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