$ @ को छोड़कर 1 तर्क


36

मुझे इस तरह से चलने वाली एक शेल स्क्रिप्ट लिखने की आवश्यकता है:

./myscript arg1 arg2_1 arg2_2 arg2_3 ....... arg2_#

स्क्रिप्ट के अंदर एक लूप है

for i in $@

हालाँकि, जैसा कि मुझे पता है, $ @ में $ 1 तक $ ($ # - 1) शामिल है। लेकिन मेरे कार्यक्रम के लिए $ 1 अलग से $ 2 $ 3 $ 4 आदि से अलग है। मैं $ 2 से अंत तक लूप करना चाहूंगा ... मैं इसे कैसे प्राप्त करूं? धन्यवाद:)

जवाबों:


47

पहले, ध्यान दें कि $@बिना उद्धरण के कोई मतलब नहीं है और इसका उपयोग नहीं किया जाना चाहिए। $@केवल उद्धृत ( "$@") और सूची संदर्भों में उपयोग किया जाना चाहिए ।

for i in "$@" सूची के संदर्भ के रूप में अर्हता प्राप्त करता है, लेकिन यहां, स्थितिगत मापदंडों पर लूप करने के लिए, विहित, सबसे पोर्टेबल और सरल रूप है:

for i
do something with "$i"
done

अब, दूसरे से शुरू होने वाले तत्वों पर लूप करने के लिए, विहित और सबसे पोर्टेबल तरीका उपयोग करना है shift:

first_arg=$1
shift # short for shift 1
for i
do something with "$i"
done

बाद में shift, जो उपयोग किया जाना था $1उसे सूची से हटा दिया गया है (लेकिन हमने इसे सहेज लिया है $first_arg) और जो अभी उपयोग में है $2वह अब अंदर है $1। स्थिति मापदंडों को बाईं ओर स्थानांतरित कर दिया गया है 1( shift 22 द्वारा स्थानांतरित करने के लिए उपयोग ...)। तो मूल रूप से, हमारा लूप लूपिंग है जो कि अंतिम तर्क के लिए दूसरा था।

साथ bash(और zshऔर ksh93, लेकिन वह यह है), एक वैकल्पिक करने के लिए है:

for i in "${@:2}"
do something with "$i"
done

लेकिन ध्यान दें कि यह मानक shवाक्यविन्यास नहीं है इसलिए इसका उपयोग उस स्क्रिप्ट में नहीं किया जाना चाहिए जो इसके साथ शुरू होती है #! /bin/sh -

में zshया yash, आप भी कर सकते हैं:

for i in "${@[3,-3]}"
do something with "$i"
done

तीसरी से तीसरी अंतिम तर्क के लिए पाश।

में zsh, सरणी के $@रूप में भी जाना जाता है $argv। तो एरे की शुरुआत या अंत से तत्वों को पॉप करने के लिए, आप यह भी कर सकते हैं:

argv[1,3]=() # remove the first 3 elements
argv[-3,-1]=()

( shiftयह भी लिखा जा सकता है 1=()में zsh)

में bash, आप केवल बिलिन वाले $@तत्वों को असाइन कर सकते हैं set, इसलिए अंत में 3 तत्वों को पॉप करने के लिए, यह कुछ इस तरह होगा:

set -- "${@:1:$#-3}"

और तीसरी से तीसरी बार लूप करने के लिए:

for i in "${@:3:$#-5}"
do something with "$i"
done

POSIXly, के अंतिम 3 तत्वों को पॉप करने के लिए "$@", आपको एक लूप का उपयोग करना होगा:

n=$(($# - 3))
for arg do
  [ "$n" -gt 0 ] && set -- "$@" "$arg"
  shift
  n=$((n - 1))
done

2
एक वैकल्पिक (और बदसूरत) बैश संभावना: अप्रत्यक्ष चर:for ((i=2; i<=$#; i++)); do something with "${!i}"; done
ग्लेन जैकमैन

मैं इस संस्करण से अधिक परिचित हूं, क्योंकि मैं c ++ :)
user40780

10

मुझे लगता है कि आप shiftबिलिन चाहते हैं । यह नाम बदलता है $2करने के लिए $1, $3करने के लिए $2, आदि

ऐशे ही:

shift
for i in "$@"; do
    echo $i
done

क्या आप अधिक विस्तार से बता सकते हैं कि मैं इसे लूप के लिए कैसे प्राप्त करूं? धन्यवाद।
1940 पर user40780

1
आप नहीं करते - आप forलूप में प्रवेश करने से पहले इसका उपयोग करते हैं , फिर आप $ @ के माध्यम से सामान्य रूप से लूप करते हैं। shiftकॉल के बाद , $ @ होना चाहिएarg2_1 arg2_2 arg2_3...
जॉन

हालाँकि, मेरे पास एक और प्रश्न होगा: मान लीजिए कि मैं $ 1 से $ ($ # - 2) तक लूप करना चाहता हूं (यानी arg_1 तक arg_2 _ # - 1, arg_2 _ # को छोड़कर) ... मुझे क्या करना चाहिए?
1940 पर user40780

2

वहाँ हमेशा गुहा दृष्टिकोण है:

first=1
for i
do
        if [ "$first" ]
        then
                first=
                continue
        fi
        something with "$i"
done

यह $@बरकरार है (यदि आप इसे बाद में उपयोग करना चाहते हैं), और बस हर तर्क पर लूप होता है, लेकिन पहले वाले को संसाधित नहीं करता है।


1

बैश में आप स्पष्ट लूपिंग के साथ उस लूप को भी लिख सकते हैं:

for ((i=2; i<=$#; ++i)); do
  process "${!i}"
done

यह दूसरे तर्कों से लेकर अंतिम एक तक सभी पर निर्भर करता है। यदि आप इसके बजाय अंतिम तर्क को छोड़ना चाहते हैं, तो बस इसे बनाएं

for ((i=1; i<=$#-1; ++i)); do
  process "${!i}"
done

और यदि आप केवल हर दूसरे तर्क को लेना चाहते हैं, तो इसे लिखें

for ((i=1; i<=$#; i+=2)); do
  process "${!i}"
done

इसके पीछे की कहानी बिल्डिन का अंकगणित संस्करण है , जिसे तर्क-गणना और चर अप्रत्यक्ष रूप से जोड़ा गया हैfor$#${…}

एक अच्छा अनुप्रयोग यह है कि आप इसे लूप के अंदर तय करने के लिए उपयोग कर सकते हैं, क्या एक दिया गया विकल्प तर्क को ले जाएगा जो इसे मूल्य के रूप में अनुसरण करता है। यदि यह करता है, तो वृद्धिशील i(जैसे लेखन : $((++i))) अगले मूल्य का उपभोग करने और पुनरावृत्ति के दौरान इसे छोड़ने के लिए।

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