Масиви в оболонці unix?


Відповіді:


91

Наступний код створює та друкує масив рядків у оболонці:

#!/bin/bash
array=("A" "B" "ElementC" "ElementE")
for element in "${array[@]}"
do
    echo "$element"
done

echo
echo "Number of elements: ${#array[@]}"
echo
echo "${array[@]}"

Результат:

A
B
ElementC
ElementE

Number of elements: 4

A B ElementC ElementE

61

в bash ви створюєте такий масив

arr=(one two three)

щоб викликати елементи

$ echo "${arr[0]}"
one
$ echo "${arr[2]}"
three

щоб попросити введення даних користувача, ви можете скористатися функцією читання

read -p "Enter your choice: " choice

Оголошення, відокремлене пробілом, НЕ працює при /bin/shвидачі помилки line 1: syntax error: unexpected "(". Ви знаєте альтернативу?
mhyousefi

20

Оболонка Борна не підтримує масиви. Однак є два шляхи вирішення проблеми.

Використовуйте позиційні параметри оболонки $ 1, $ 2 тощо:

$ set one two three
$ echo $*
one two three
$ echo $#
3
$ echo $2
two

Використовуйте оцінки змінних:

$ n=1 ; eval a$n="one" 
$ n=2 ; eval a$n="two" 
$ n=3 ; eval a$n="three"
$ n=2
$ eval echo \$a$n
two

1
Bash підтримує масиви. Не впевнений в оригінальній оболонці Борна, але баш сьогодні є більш поширеним ...
plesiv

2
@zplesivcak - ... на GNU / Linux, оскільки це річ GNU. Наприклад, FreeBSD не постачається bash(його можна встановити з портів). Сценарії, написані з припущенням, що bashфункції не є портативними, і вони помітно повільніші та повільніші, ніж більшість реалізацій оболонки Борна (наприклад dash, що є загальним у дистрибутивах GNU / Linux). bashце приємна інтерактивна оболонка, але це сценарій повільний.
beatgammit

1
$*вважається шкідливим. Зазвичай $@переважно, оскільки він робить те саме, але зберігає пробіли. $@розширюється як "$ 1" "$ 2" "$ 3" ... "$ n", тоді $*як розширюється як "$ 1x $ 2x $ 3x ... $ n", де xє $IFSроздільник (швидше за все, пробіл).
zserge

1
Без котирувань $@- те саме, що $*; різниця проявляється лише при цитуванні: "$*"це одне слово, при цьому "$@"зберігаються вихідні розриви слів.
Марк Рід

Питання позначено тегами bash, тому відповіді на конкретні bash є доречними, але, безумовно, правда, не слід вважати, що /bin/shце bash.
Марк Рід

13
#!/bin/bash

# define a array, space to separate every item
foo=(foo1 foo2)

# access
echo "${foo[1]}"

# add or changes
foo[0]=bar
foo[2]=cat
foo[1000]=also_OK

Ви можете прочитати АБС "Розширений посібник із написання скриптів"


3
Будь ласка, перегляньте пропозицію АБС як навчального ресурсу - це багато в чому розбивати те, що таке W3Schools для HTML та Javascript, маючи багато Google соку, але демонструючи погані практики у багатьох його прикладах, і рідко та неадекватно оновлюється. Вікі-програма хакерів - набагато кращий ресурс; так само як і BashGuide .
Чарльз Даффі

Оголошення, відокремлене пробілом, НЕ працює при /bin/shвидачі помилки line 1: syntax error: unexpected "(". Ви знаєте альтернативу?
mhyousefi

8

Оболонка Борна і оболонка C не мають масивів, IIRC.

На додаток до сказаного іншими, у Bash ви можете отримати кількість елементів у масиві наступним чином:

elements=${#arrayname[@]}

і виконувати операції в стилі фрагментів:

arrayname=(apple banana cherry)
echo ${arrayname[@]:1}                   # yields "banana cherry"
echo ${arrayname[@]: -1}                 # yields "cherry"
echo ${arrayname[${#arrayname[@]}-1]}    # yields "cherry"
echo ${arrayname[@]:0:2}                 # yields "apple banana"
echo ${arrayname[@]:1:1}                 # yields "banana"

csh має масиви.
Кіт Томпсон,

@KeithThompson: Це не задокументовано на сторінці користувача, але функціональність, мабуть, присутня принаймні в деяких версіях.
Денніс Вільямсон

3
Сторінка користувача не згадує "масиви" з цією назвою, але дивіться документацію до setкоманди ( set name=(wordlist)) та розділу "Заміна змінних" ( $name[selector]і ${name[selector]}). Наскільки мені відомо, csh завжди підтримував масиви. Дивіться, наприклад, $pathзмінну масиву, яка відображає $PATHзмінну середовища.
Кіт Томпсон,

8

Спробуйте це :

echo "Find the Largest Number and Smallest Number of a given number"
echo "---------------------------------------------------------------------------------"
echo "Enter the number"
read n
i=0

while [ $n -gt 0 ] #For Seperating digits and Stored into array "x"
do
        x[$i]=`expr $n % 10`
        n=`expr $n / 10`
        i=`expr $i + 1`
done

echo "Array values ${x[@]}"  # For displaying array elements


len=${#x[*]}  # it returns the array length


for (( i=0; i<len; i++ ))    # For Sorting array elements using Bubble sort
do
    for (( j=i+1; j<len;  j++ ))
    do
        if [ `echo "${x[$i]} > ${x[$j]}"|bc` ]
        then
                t=${x[$i]}
                t=${x[$i]}
                x[$i]=${x[$j]}
                x[$j]=$t
        fi
        done
done


echo "Array values ${x[*]}"  # Displaying of Sorted Array


for (( i=len-1; i>=0; i-- ))  # Form largest number
do
   a=`echo $a \* 10 + ${x[$i]}|bc`
done

echo "Largest Number is : $a"

l=$a  #Largest number

s=0
while [ $a -gt 0 ]  # Reversing of number, We get Smallest number
do
        r=`expr $a % 10`
        s=`echo "$s * 10 + $r"|bc`
        a=`expr $a / 10`
done
echo "Smallest Number is : $s" #Smallest Number

echo "Difference between Largest number and Smallest number"
echo "=========================================="
Diff=`expr $l - $s`
echo "Result is : $Diff"


echo "If you try it, We can get it"

6

Ваше запитання стосується "скриптів оболонки unix", але позначено тегами bash. Це дві різні відповіді.

Специфікація POSIX для оболонок не має нічого сказати про масиви, оскільки оригінальна оболонка Борна їх не підтримувала. Навіть сьогодні на FreeBSD, Ubuntu Linux та багатьох інших системах /bin/shнемає підтримки масивів. Отже, якщо ви хочете, щоб ваш сценарій працював у різних оболонках, сумісних з Борном, не слід їх використовувати. Якщо ж ви припускаєте конкретну оболонку, то обов’язково вкажіть її повне ім’я в рядку shebang, наприклад#!/usr/bin/env bash .

Якщо ви використовуєте bash або zsh , або сучасну версію ksh , ви можете створити такий масив:

myArray=(first "second element" 3rd)

і отримати доступ до таких елементів

$ echo "${myArray[1]}"
second element

Ви можете отримати всі елементи через "${myArray[@]}". Ви можете використовувати позначення зрізу $ {array [@]: start: length}, щоб обмежити частину посиланого масиву, наприклад, "${myArray[@]:1}"щоб залишити перший елемент.

Довжина масиву становить ${#myArray[@]}. Ви можете отримати новий масив, що містить усі індекси з існуючого масиву з "${!myArray[@]}".

У старих версіях ksh до ksh93 також були масиви, але не позначення на основі дужок, і вони не підтримували нарізання. Однак ви можете створити такий масив:

set -A myArray -- first "second element" 3rd 

5

Ви можете спробувати наступного типу:

#!/bin/bash
 declare -a arr

 i=0
 j=0

  for dir in $(find /home/rmajeti/programs -type d)
   do
        arr[i]=$dir
        i=$((i+1))
   done


  while [ $j -lt $i ]
  do
        echo ${arr[$j]}
        j=$((j+1))
  done

розриви імен каталогів з пробілами. використовуйте цикл читання на час зміни IFS, щоб подбати про це.
ghostdog74

5

Масив можна завантажувати двома шляхами.

set -A TEST_ARRAY alpha beta gamma

або

X=0 # Initialize counter to zero.

- Завантажте масив з рядками альфа, бета та гама

for ELEMENT in alpha gamma beta
do
    TEST_ARRAY[$X]=$ELEMENT
    ((X = X + 1))
done

Крім того, я думаю, що нижченаведена інформація може допомогти:

Оболонка підтримує одновимірні масиви. Максимальна кількість елементів масиву - 1024. Коли масив визначено, він автоматично розмірюється до 1024 елементів. Одновимірний масив містить послідовність елементів масиву, які нагадують вагони, з'єднані між собою на залізничній колії.

Якщо ви хочете отримати доступ до масиву:

echo ${MY_ARRAY[2] # Show the third array element
 gamma 


echo ${MY_ARRAY[*] # Show all array elements
-   alpha beta gamma


echo ${MY_ARRAY[@] # Show all array elements
 -  alpha beta gamma


echo ${#MY_ARRAY[*]} # Show the total number of array elements
-   3


echo ${#MY_ARRAY[@]} # Show the total number of array elements
-   3

echo ${MY_ARRAY} # Show array element 0 (the first element)
-  alpha

4

Якщо ви хочете сховище значень ключа з підтримкою пробілів, використовуйте -Aпараметр:

declare -A programCollection
programCollection["xwininfo"]="to aquire information about the target window."

for program in ${!programCollection[@]}
do
    echo "The program ${program} is used ${programCollection[${program}]}"
done

http://linux.die.net/man/1/bash "Асоціативні масиви створюються за допомогою оголошення -A ім'я."


4

Існує кілька способів створити масив в оболонці.

ARR[0]="ABC"
ARR[1]="BCD"
echo ${ARR[*]}

${ARR[*]} друкує всі елементи масиву.

Другий спосіб:

ARR=("A" "B" "C" "D" 5 7 "J")
echo ${#ARR[@]}
echo ${ARR[0]}

${#ARR[@]} використовується для підрахунку довжини масиву.


Приємна відповідь, чудовий старт для новачка. І ласкаво просимо на рівні голосування ;-)
GhostCat

3

Для зчитування значень з клавіатури та вставки елемента в масив

# enter 0 when exit the insert element
echo "Enter the numbers"
read n
while [ $n -ne 0 ]
do
    x[$i]=`expr $n`
    read n
    let i++
done

#display the all array elements
echo "Array values ${x[@]}"
echo "Array values ${x[*]}"

# To find the array length
length=${#x[*]}
echo $length

1

У ksh ви це робите:

set -A array element1 element2 elementn

# view the first element
echo ${array[0]}

# Amount elements (You have to substitute 1)
echo ${#array[*]}

# show last element
echo ${array[ $(( ${#array[*]} - 1 )) ]}

Більш стислий спосіб показати останній елемент - це echo "${array[@]:(-1)}". Це позбавляє від необхідності писати ім'я змінної масиву двічі.
Alex Dupuy

1

Простий спосіб:

arr=("sharlock"  "bomkesh"  "feluda" )  ##declare array

len=${#arr[*]}  #determine length of array

# iterate with for loop
for (( i=0; i<len; i++ ))
do
    echo ${arr[$i]}
done
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.