बाश में एक सरणी में कमांड लाइन तर्क परिवर्तित करें


160

मैं कमांड-लाइन आर्ग्युमेंट्स को बैश स्क्रिप्ट ऐरे में कैसे बदल सकता हूँ?

मैं इसे लेना चाहता हूं:

./something.sh arg1 arg2 arg3

और इसे करने के लिए परिवर्तित

myArray=( arg1 arg2 arg3 )

ताकि मैं स्क्रिप्ट में आगे उपयोग के लिए myArray का उपयोग कर सकूं।

यह पिछला SO पोस्ट करीब आता है, लेकिन यह सरणी बनाने के तरीके में नहीं जाता है: मैं कैसे बैश में कमांड लाइन तर्क को पार्स कर सकता हूं?

मुझे तर्कों को एक नियमित बैश स्क्रिप्ट सरणी में बदलने की आवश्यकता है; मुझे लगता है कि मैं अन्य भाषाओं (उदाहरण के लिए पायथन) का उपयोग कर सकता हूं, लेकिन इसे बाश में करने की आवश्यकता है। मुझे लगता है कि मैं "एपेंड" फ़ंक्शन या कुछ इसी तरह की तलाश में हूं?

अद्यतन: मैं यह भी पूछना चाहता था कि शून्य तर्कों की जांच कैसे करें और एक डिफ़ॉल्ट सरणी मान असाइन करें, और नीचे दिए गए उत्तर के लिए धन्यवाद, यह काम पाने में सक्षम था:

if [ "$#" -eq 0 ]; then
  myArray=( defaultarg1 defaultarg2 )
else
  myArray=( "$@" )
fi

जवाबों:


206

वास्तव में आपके कमांड लाइन तर्क व्यावहारिक रूप से पहले से ही एक सरणी की तरह हैं । कम से कम, आप $@एक सरणी की तरह चर का इलाज कर सकते हैं । उस ने कहा, आप इसे इस तरह एक वास्तविक सरणी में बदल सकते हैं:

myArray=( "$@" )

यदि आप केवल कुछ तर्क टाइप करना चाहते हैं और उन्हें $@मूल्य में फीड करना चाहते हैं , तो उपयोग करें set:

$ set -- apple banana "kiwi fruit"
$ echo "$#"
3
$ echo "$@"
apple banana kiwi fruit

यह समझने के लिए कि तर्क संरचना का उपयोग कैसे किया जाता है, विशेष रूप से POSIX sh में उपयोगी है, जिसमें एक सरणी जैसा कुछ और नहीं है।


2
धन्यवाद! बहुत अच्छा काम करता है! क्या यह पूछने के बारे में था कि शून्य तर्कों की जांच कैसे करें और एक डिफ़ॉल्ट सरणी मान असाइन करें, और $ # इसके लिए पूरी तरह से काम करता है!
सुमन

1
setआपको स्कोप के लिए स्थितीय पैरामीटर सेट करने की अनुमति देता है। यह आपको शेल विकल्प भी सेट करने देता है। आप कर सकते हैं set foo, जिसका अर्थ $1"फू" तक फैल जाएगा , लेकिन अगर आपके पैरामीटर डैश setसे शुरू होते हैं, तो आप मान लेंगे कि शेल विकल्प सेट करना है। डबल-डैश यह सुनिश्चित करता है कि निम्नलिखित सभी मापदंडों को सेट करने के लिए स्थितीय मापदंडों के रूप में व्याख्या की गई है।
कोजिरो

11
एक गेटा: echo $@सभी तर्कों को प्रिंट करेगा, लेकिन echo $myArrayकेवल पहले तत्व को प्रिंट करेगा। उन सभी को देखने के लिए, का उपयोग करें echo ${myArray[@]}
z0r

4
@ z0r यदि आप उन विस्तार के आसपास दोहरे उद्धरण नहीं देते हैं, तो बैश उन्हें फिर से जोड़ देगा, और संभवतः अर्थ खो देगा।
कोजीरो

सही, एक एरे को "स्प्लिट" करने का सामान्य तरीका और प्रत्येक तत्व का उपयोग करना है "${myArray[@]}"। यदि आप सरणी के माध्यम से लूप करना चाहते हैं, तो आपको IFS पर इसके व्यक्तिगत तत्वों के विभाजन से बचने के लिए उद्धरणों की आवश्यकता है
BallpointBen

66

शायद यह मदद कर सकता है:

myArray=("$@") 

यह भी कि आप 'में' छोड़ कर तर्कों पर पुनरावृति कर सकते हैं:

for arg; do
   echo "$arg"
done

के बराबर होगा

for arg in "${myArray[@]}"; do
   echo "$arg"
done

3
नौसिखिया सवाल: कैसे बश को पता है कि argक्षेत्र में क्या करना है - क्या यह एक पूर्वनिर्धारित चर है? ${var}की सामग्री तक विस्तारित है var। सरणी ${var[n]}के तत्व nकी सामग्री तक विस्तारित है var। है ${var[@]}तो पूरे सरणी, यानी के विस्तार ${var[0]} ${var[1]} ... ${var[n]}(के साथ nपिछले तत्व के सूचकांक जा रहा है)?
ईसाई

4
[के लिए] बिना [में] तर्कों पर पाश $ @ ($ 1, $ 2, आदि) होगा। जिसे [सेट] कमांड के साथ भी सेट किया जा सकता है, उदाहरण के लिए सेट करें - arg1 arg2
नहुएल फौइउल सिप

17

वास्तव में मापदंडों की सूची $1 $2 ...आदि के साथ पहुँचा जा सकता है,
जो इसके बराबर है:

${!i}

इसलिए, मापदंडों की सूची को सेट के साथ बदला जा सकता है,
और ${!i}उन्हें एक्सेस करने का सही तरीका है:

$ set -- aa bb cc dd 55 ff gg hh ii jjj kkk lll
$ for ((i=0;i<=$#;i++)); do echo "$#" "$i" "${!i}"; done
12 1 aa
12 2 bb
12 3 cc
12 4 dd
12 5 55
12 6 ff
12 7 gg
12 8 hh
12 9 ii
12 10 jjj
12 11 kkk
12 12 lll

आपके विशिष्ट मामले के लिए, इसका उपयोग किया जा सकता है (सरणियों की आवश्यकता के बिना), तर्कों की सूची सेट करने के लिए जब कोई नहीं दिया गया था:

if [ "$#" -eq 0 ]; then
    set -- defaultarg1 defaultarg2
fi

जो इस और भी सरल अभिव्यक्ति में अनुवाद करता है:

[ "$#" == "0" ] && set -- defaultarg1 defaultarg2

क्या प्रतिध्वनि का उदाहरण नहीं होना चाहिए: echo "$#" "$i+1" "${!i}";जैसा कि दिखाया गया है आउटपुट प्राप्त करना?
ज़ेल

6

यहाँ एक और उपयोग है:

#!/bin/bash
array=( "$@" )
arraylength=${#array[@]}
for (( i=0; i<${arraylength}; i++ ));
do
   echo "${array[$i]}"
done

4

आसान फिर भी, आप सीधे पर काम कर सकते हैं $@;)

यहाँ कैसे शीघ्र से सीधे आर्ग की एक सूची पास करने के लिए है:

function echoarg { for stuff in "$@" ; do echo $stuff ; done ; } 
    echoarg Hey Ho Lets Go
    Hey
    Ho
    Lets
    Go

1
और भी आसान, for stuff in "$@" ; do ...रूप में ही है for stuff ; do ...:)
kKm

1

अगल-बगल के दृश्य कैसे सरणी और $ @ व्यावहारिक रूप से समान हैं।

कोड:

#!/bin/bash

echo "Dollar-1 : $1"
echo "Dollar-2 : $2"
echo "Dollar-3 : $3"
echo "Dollar-AT: $@"
echo ""

myArray=( "$@" )

echo "A Val 0: ${myArray[0]}"
echo "A Val 1: ${myArray[1]}"
echo "A Val 2: ${myArray[2]}"
echo "A All Values: ${myArray[@]}"

इनपुट:

./bash-array-practice.sh 1 2 3 4

आउटपुट:

Dollar-1 : 1
Dollar-2 : 2
Dollar-3 : 3
Dollar-AT: 1 2 3 4

A Val 0: 1
A Val 1: 2
A Val 2: 3
A All Values: 1 2 3 4

1

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

कोड:

#!/bin/bash
printf 'arguments:%s\n' "$@"
declare -a arrayGOOD=( "$@" )
declare -a arrayBAAD=(  $@  )

printf '\n%s:\n' arrayGOOD
declare -p arrayGOOD
arrayGOODlength=${#arrayGOOD[@]}
for (( i=1; i<${arrayGOODlength}+1; i++ ));
do
   echo "${arrayGOOD[$i-1]}"
done

printf '\n%s:\n' arrayBAAD
declare -p arrayBAAD
arrayBAADlength=${#arrayBAAD[@]}
for (( i=1; i<${arrayBAADlength}+1; i++ ));
do
   echo "${arrayBAAD[$i-1]}"
done

आउटपुट:

> ./bash-array-practice.sh 'The dog ate the "flea" -- and ' the mouse.
arguments:The dog ate the "flea" -- and 
arguments:the
arguments:mouse.

arrayGOOD:
declare -a arrayGOOD='([0]="The dog ate the \"flea\" -- and " [1]="the" [2]="mouse.")'
The dog ate the "flea" -- and 
the
mouse.

arrayBAAD:
declare -a arrayBAAD='([0]="The" [1]="dog" [2]="ate" [3]="the" [4]="\"flea\"" [5]="--" [6]="and" [7]="the" [8]="mouse.")'
The
dog
ate
the
"flea"
--
and
the
mouse.
> 
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.