Komut satırı bağımsız değişkenlerini Bash'teki bir diziye dönüştürme


162

Komut satırı bağımsız değişkenlerini bash komut dizisine nasıl dönüştürebilirim?

Bunu almak istiyorum:

./something.sh arg1 arg2 arg3

ve

myArray=( arg1 arg2 arg3 )

böylece komut dosyasında daha fazla kullanım için myArray kullanabilirsiniz.

Bu önceki SO yayını yaklaşıyor, ancak nasıl bir dizi oluşturulacağını anlatmıyor: Bash'de komut satırı bağımsız değişkenlerini nasıl ayrıştırırım?

Değişkenleri düzenli bash komut dizisine dönüştürmek gerekiyor; Diğer dilleri (örneğin Python) kullanabileceğimin farkındayım ama bunu bash'da yapmam gerekiyor. Sanırım bir "append" fonksiyonu ya da benzeri bir şey arıyorum?

GÜNCELLEME: Ayrıca sıfır bağımsız değişkenleri nasıl kontrol edeceğinizi ve varsayılan bir dizi değeri atayacağımı sormak istedim ve aşağıdaki cevap sayesinde bu çalışmayı elde edebildim:

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

Yanıtlar:


209

Aslında komut satırı argümanları vardır pratikte zaten bir dizi gibi. En azından, $@değişkene bir dizi gibi davranabilirsiniz. Bununla birlikte, bunun gibi gerçek bir diziye dönüştürebileceğinizi söyledi:

myArray=( "$@" )

Yalnızca bazı bağımsız değişkenler yazmak ve bunları $@değere beslemek istiyorsanız , şunu kullanın set:

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

Argüman yapısının nasıl kullanılacağını anlamak, bir dizi gibi başka bir şeye sahip olmayan POSIX sh'de özellikle yararlıdır.


2
Teşekkürler! Harika çalışıyor! Sıfır argümanlarının nasıl kontrol edileceğini ve varsayılan bir dizi değerinin nasıl atanacağını sormak üzereydi ve $ # bunun için mükemmel çalışıyor!
Suman

1
setkapsam için konum parametreleri ayarlamanıza olanak tanır. Ayrıca kabuk seçeneklerini ayarlamanızı sağlar. Bunu yapabilirsiniz set foo, bu da $1"foo" 'ya genişleyecektir, ancak parametreleriniz bir tire işareti ile başlıyorsa, setbir kabuk seçeneği ayarlamak istediğinizi varsayar. Çift tire, aşağıdaki tüm parametrelerin ayarlanacak konum parametreleri olarak yorumlanmasını sağlar.
kojiro

12
Bir gotcha: echo $@tüm argümanları basar , ancak echo $myArraysadece ilk elemanı basar. Hepsini görmek için kullanın echo ${myArray[@]}.
z0r

4
@ z0r Bu açılımların etrafına çift tırnak koymazsanız, bash onları yeniden sözcüklendirir ve muhtemelen anlamını kaybeder.
kojiro

Doğru, bir dizi "uyarmak" ve her öğeyi kullanmak için genel yoludur "${myArray[@]}". Dizi boyunca döngü yapmak istiyorsanız, IFS
BallpointBen

67

Belki bu yardımcı olabilir:

myArray=("$@") 

ayrıca 'in' parametresini atlayarak argümanlar üzerinde yineleme yapabilirsiniz:

for arg; do
   echo "$arg"
done

eşdeğer olacak

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

3
Acemi sorular: bash argalana ne koyacağını nasıl biliyor - önceden tanımlanmış bir değişken mi? ${var}içeriğine genişletildi var. dizi ${var[n]}öğesinin içeriğine genişletilir . Is sonra tüm dizi yani genişleyen (ile geçen elementin endeksi olmak üzere)? nvar${var[@]}${var[0]} ${var[1]} ... ${var[n]}n
Christian

4
[in] olmadan [for], $ @ ($ 1, $ 2, vb.) argümanları üzerinde döngü yapar. [Set] komutuyla da ayarlanabilir, örneğin set - arg1 arg2
Nahuel Fouilleul 28:16

17

Aslında parametre listesine $1 $2 ...vb.
İle erişilebilir .

${!i}

Bu nedenle, parametre listesi set ile değiştirilebilir
ve ${!i}bunlara erişmek için doğru yoldur:

$ 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

Özel durumunuz için bu, hiçbir dizinin verilmediği durumlarda argüman listesini ayarlamak için kullanılabilir (dizilere ihtiyaç duyulmadan):

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

bu daha da basit ifadeye dönüşür:

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

Eko örneği şöyle olmamalı: echo "$#" "$i+1" "${!i}";çıktıyı tam olarak gösterildiği gibi almak için mi?
Zael

6

İşte başka bir kullanım:

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

4

Daha kolay Yine de, doğrudan $@ ;)

Doğrudan komut isteminden bir bağımsız değişken listesini nasıl geçireceğiniz aşağıda açıklanmıştır:

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

1
Daha da kolay, for stuff in "$@" ; do ...aynıdır for stuff ; do ...:)
kkm

1

Dizinin ve $ @ uygulamasının pratikte nasıl aynı olduğuna yan yana bakış.

Kod:

#!/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[@]}"

Giriş:

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

Çıktı:

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

Çift tırnakların önemi üzerinde durulmaya değer. Bir bağımsız değişkenin boşluk içerdiğini varsayalım.

Kod:

#!/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

Çıktı:

> ./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.
> 
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.