Mảng trong unix shell?


Câu trả lời:


90

Đoạn mã sau tạo và in một mảng chuỗi trong shell:

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

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

Kết quả:

A
B
ElementC
ElementE

Number of elements: 4

A B ElementC ElementE

61

trong bash, bạn tạo mảng như thế này

arr=(one two three)

để gọi các phần tử

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

để yêu cầu người dùng nhập, bạn có thể sử dụng read

read -p "Enter your choice: " choice

Khai báo được phân tách bằng dấu cách KHÔNG hoạt động với /bin/shviệc đưa ra lỗi line 1: syntax error: unexpected "(". Bạn có biết về một giải pháp thay thế?
mhyousefi

20

Bourne shell không hỗ trợ mảng. Tuy nhiên, có hai cách để xử lý vấn đề.

Sử dụng các tham số shell vị trí $ 1, $ 2, v.v.:

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

Sử dụng các đánh giá biến:

$ 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 hỗ trợ mảng. Không chắc chắn về vỏ Bourne ban đầu, nhưng bash phổ biến hơn những ngày này ...
plesiv

2
@zplesivcak - ... trên GNU / Linux, vì nó là một thứ GNU. Ví dụ: FreeBSD không đi kèm bash(mặc dù nó có thể cài đặt từ các cổng). Các tập lệnh được viết giả sử bashcác tính năng không di động và chúng chậm hơn đáng kể so với hầu hết các triển khai trình bao Bourne (như dash, điều này phổ biến trên các bản phân phối GNU / Linux). bashlà một trình bao tương tác tốt, nhưng nó chậm cho việc viết kịch bản.
beatgammit

1
$*được coi là có hại. Thông thường, $@được ưu tiên hơn vì nó làm tương tự, nhưng giữ khoảng cách. $@được mở rộng thành "$ 1" "$ 2" "$ 3" ... "$ n", trong khi $*được mở rộng thành "$ 1x $ 2x $ 3x ... $ n", trong đó x$IFSdấu phân cách (rất có thể là dấu cách).
zserge

1
Không được trích dẫn, $@cũng giống như $*; sự khác biệt chỉ hiển thị khi được trích dẫn: "$*"là một từ, trong khi "$@"giữ nguyên các ngắt từ gốc.
Mark Reed

Câu hỏi được gắn thẻ bash, do đó, các câu trả lời dành riêng cho bash là phù hợp, nhưng chắc chắn đúng là người ta không nên cho rằng đó /bin/shlà bash.
Mark Reed

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

Bạn có thể đọc "Hướng dẫn viết kịch bản nâng cao" của ABS


3
Vui lòng xem xét lại việc đề xuất ABS như một tài nguyên học tập - theo nhiều cách để hiểu W3Schools là gì đối với HTML và Javascript, có rất nhiều nước ép của Google nhưng hiển thị các phương pháp không tốt trong nhiều ví dụ và hiếm khi được cập nhật không đầy đủ. Wiki của bash-hacker là một nguồn tài nguyên tốt hơn nhiều; như vậy là BashGuide .
Charles Duffy

Khai báo được phân tách bằng dấu cách KHÔNG hoạt động với /bin/shviệc đưa ra lỗi line 1: syntax error: unexpected "(". Bạn có biết về một giải pháp thay thế?
mhyousefi

8

Bourne shell và C shell không có mảng, IIRC.

Ngoài những gì người khác đã nói, trong Bash, bạn có thể nhận được số phần tử trong một mảng như sau:

elements=${#arrayname[@]}

và thực hiện các thao tác kiểu lát:

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 không có mảng.
Keith Thompson

@KeithThompson: Nó không được ghi lại trong trang người đàn ông nhưng chức năng này dường như có mặt trong ít nhất một số phiên bản.
Tạm dừng cho đến khi có thông báo mới.

3
Trang người đàn ông không đề cập đến "mảng" bằng tên đó, nhưng hãy xem tài liệu về setlệnh ( set name=(wordlist)) và phần "Nhóm thay thế biến" ( $name[selector]${name[selector]}). Theo như tôi biết, csh luôn hỗ trợ các mảng. Ví dụ, hãy xem $pathbiến mảng, phản ánh $PATHbiến môi trường.
Keith Thompson

8

Thử đi :

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"

Điều này chỉ hoạt động trong ksh và bash, phải không?
Lassi

6

Câu hỏi của bạn hỏi về "unix shell scripting", nhưng được gắn thẻ bash. Đó là hai câu trả lời khác nhau.

Đặc tả POSIX cho shell không có bất cứ điều gì để nói về mảng, vì Bourne shell ban đầu không hỗ trợ chúng. Ngay cả ngày nay, trên FreeBSD, Ubuntu Linux và nhiều hệ thống khác, /bin/shvẫn chưa hỗ trợ mảng. Vì vậy, nếu bạn muốn tập lệnh của mình hoạt động trong các trình bao tương thích với Bourne khác nhau, bạn không nên sử dụng chúng. Ngoài ra, nếu bạn đang giả định một trình bao cụ thể, thì hãy đảm bảo đặt tên đầy đủ của nó trong dòng shebang, ví dụ #!/usr/bin/env bash.

Nếu bạn đang sử dụng bash hoặc zsh hoặc phiên bản ksh hiện đại , bạn có thể tạo một mảng như sau:

myArray=(first "second element" 3rd)

và truy cập các phần tử như thế này

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

Bạn có thể nhận được tất cả các yếu tố thông qua "${myArray[@]}". Bạn có thể sử dụng ký hiệu lát cắt $ {array [@]: start: length} để hạn chế phần của mảng được tham chiếu, ví dụ: "${myArray[@]:1}"bỏ đi phần tử đầu tiên.

Chiều dài của mảng là ${#myArray[@]}. Bạn có thể lấy một mảng mới chứa tất cả các chỉ mục từ một mảng hiện có với "${!myArray[@]}".

Các phiên bản cũ hơn của ksh trước ksh93 cũng có mảng, nhưng không phải là ký hiệu dựa trên dấu ngoặc đơn, cũng như không hỗ trợ cắt. Tuy nhiên, bạn có thể tạo một mảng như thế này:

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

5

Bạn có thể thử loại sau:

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

ngắt trên tên thư mục có dấu cách. sử dụng vòng lặp đọc trong khi thay đổi IFS để xử lý điều đó.
ghostdog 74

5

Một mảng có thể được tải trong hai ngày.

set -A TEST_ARRAY alpha beta gamma

hoặc là

X=0 # Initialize counter to zero.

- Tải mảng với các chuỗi alpha, beta và gamma

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

Ngoài ra, tôi nghĩ thông tin dưới đây có thể giúp ích:

Vỏ hỗ trợ mảng một chiều. Số phần tử mảng tối đa là 1,024. Khi một mảng được xác định, nó sẽ tự động được định kích thước thành 1.024 phần tử. Mảng một chiều chứa một chuỗi các phần tử của mảng, chúng giống như những chiếc xế hộp được kết nối với nhau trên đường tàu.

Trong trường hợp bạn muốn truy cập vào mảng:

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

Nếu bạn muốn lưu trữ giá trị khóa có hỗ trợ khoảng trắng, hãy sử dụng -Atham số:

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 "Mảng liên kết được tạo bằng tên khai báo -A."


4

Có nhiều cách để tạo một mảng trong shell.

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

${ARR[*]} in tất cả các phần tử trong mảng.

Cách thứ hai là:

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

${#ARR[@]} được sử dụng để đếm độ dài của mảng.


Câu trả lời tuyệt vời, Khởi đầu tuyệt vời cho một người mới. Và chào mừng đến với các cấp độ
ủng hộ

3

Để đọc các giá trị từ keybord và chèn phần tử vào mảng

# 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

Trong ksh bạn làm điều đó:

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 )) ]}

Một cách ngắn gọn hơn để hiển thị phần tử cuối cùng là echo "${array[@]:(-1)}". Điều này giúp loại bỏ sự cần thiết phải viết tên biến mảng hai lần.
Alex Dupuy

1

Một cách đơn giản:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.