Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> การเขียนโปรแกรม Bash

เชี่ยวชาญการดำเนินการอาร์เรย์ใน Bash Shell Scripting – ตอนที่ 8

เราไม่สามารถจินตนาการภาษาโปรแกรมโดยไม่มีแนวคิดอาร์เรย์ได้ ไม่ว่าจะถูกนำไปใช้อย่างไรในภาษาต่างๆ อาร์เรย์ช่วยให้เรารวมข้อมูล ที่คล้ายหรือต่างกัน ภายใต้ชื่อเดียวกัน

การเริ่มต้นและการใช้อาร์เรย์

ใน Bash รุ่นใหม่ รองรับอาร์เรย์มิติเดียว สามารถประกาศอาร์เรย์ได้อย่างชัดเจนด้วย declare shell-builtin

declare -a var

แต่ไม่จำเป็นต้องประกาศตัวแปรอาร์เรย์เหมือนข้างต้น เราสามารถแทรกองค์ประกอบแต่ละตัวเข้าอาร์เรย์โดยตรงได้ดังนี้

var[XX]=<value>

ที่ 'XX' หมายถึงดัชนีอาร์เรย์ ในการอ้างอิงองค์ประกอบอาร์เรย์ ใช้ไวยากรณ์วงเล็บปีกกา คือ

${var[XX]}

หมายเหตุ: การจัดทำดัชนีอาร์เรย์เริ่มต้นที่ 0 เสมอ

อีกวิธีสะดวกในการเริ่มต้นอาร์เรย์ทั้งหมดคือการใช้คู่ของวงเล็บวงกลม ดังนี้

var=( element1 element2 element3 . . . elementN )

ยังมีอีกวิธีหนึ่งในการกำหนดค่าให้อาร์เรย์ วิธีนี้เป็นหมวดย่อยของวิธีที่อธิบายไปก่อนหน้า

array=( [XX]=<value> [XX]=<value> . . . )

เรายังสามารถอ่าน/กำหนดค่าให้อาร์เรย์ในระหว่างรันไทม์ด้วย read shell-builtin

read -a array

ตอนนี้เมื่อรันคำสั่งข้างต้นในสคริปต์ มันจะรออินพุต เราต้องให้องค์ประกอบอาร์เรย์คั่นด้วยช่องว่าง (ไม่ใช่ carriage return) หลังจากใส่ค่าแล้วกด Enter เพื่อจบ

ในการวนลูปผ่านองค์ประกอบอาร์เรย์ เราสามารถใช้ for loop ได้

for i in "${array[@]}"
do
    #access each element as $i
    ...
done

สคริปต์ต่อไปนี้สรุปเนื้อหาของส่วนนี้

#!/bin/bash
array1[0]=one
array1[1]=1
echo ${array1[0]}
echo ${array1[1]}
array2=( one two three )
echo ${array2[0]}
echo ${array2[2]}
array3=( [9]=nine [11]=11 )
echo ${array3[9]}
echo ${array3[11]}
read -a array4
for i in "${array4[@]}"
do
    echo $i
done
exit 0

การดำเนินการต่างๆ บนอาร์เรย์

การดำเนินการสตริงมาตรฐานหลายอย่างทำงานบนอาร์เรย์ได้ ดูสคริปต์ตัวอย่างต่อไปนี้ที่นำการดำเนินการบนอาร์เรย์ไปปฏิบัติ (รวมถึงการดำเนินการสตริง)

#!/bin/bash
array=( apple bat cat dog elephant frog )
#print first element
echo ${array[0]}
echo ${array:0}
#display all elements
echo ${array[@]}
echo ${array[@]:0}
#display all elements except first one
echo ${array[@]:1}
#display elements in a range
echo ${array[@]:1:4}
#length of first element
echo ${#array[0]}
echo ${#array}
#number of elements
echo ${#array[*]}
echo ${#array[@]}
#replacing substring
echo ${array[@]//a/A}
exit 0

ผลลัพธ์ที่ได้จากการรันสคริปต์ข้างต้น

apple
apple
apple bat cat dog elephant frog
apple bat cat dog elephant frog
bat cat dog elephant frog
bat cat dog elephant
5
5
6
6
Apple bAt cAt dog elephAnt frog

คิดว่าไม่มีความหมายในการอธิบายสคริปต์ข้างต้นอย่างละเอียด เพราะมันอธิบายตัวเองได้แล้ว หากจำเป็น ผมจะแยกส่วนหนึ่งในซีรีส์นี้เพื่อการจัดการสตริงอย่างเฉพาะเจาะจง

การแทนที่คำสั่งกับอาร์เรย์ (Command Substitution with Arrays)

Command substitution กำหนดเอาต์พุตของคำสั่งหนึ่งหรือหลายคำสั่งไปยังบริบทอื่น ในบริบทของอาร์เรย์ เราสามารถแทรกเอาต์พุตของคำสั่งเป็นองค์ประกอบแต่ละตัวของอาร์เรย์ ไวยากรณ์ดังนี้

array=( $(command) )

โดยค่าเริ่มต้น เนื้อหาในเอาต์พุตของคำสั่งที่คั่นด้วยช่องว่างจะถูกแทรกเข้าไปในอาร์เรย์เป็นองค์ประกอบแต่ละตัว สคริปต์ต่อไปนี้แสดงรายการเนื้อหาของไดเรกทอรี ซึ่งเป็นไฟล์ที่มีสิทธิ์ 755

#!/bin/bash
ERR=27
EXT=0
if [ $# -ne 1 ]; then
    echo "Usage: $0 "
    exit $ERR
fi
if [ ! -d $1 ]; then
    echo "Directory $1 doesn't exists"
    exit $ERR
fi
temp=( $(find $1 -maxdepth 1 -type f) )
for i in "${temp[@]}"
do
    perm=$(ls -l $i)
    if [ `expr ${perm:0:10} : "-rwxr-xr-x"` -eq 10 ]; then
        echo ${i##*/}
    fi
done
exit $EXT

การจำลองอาร์เรย์สองมิติ

เราสามารถแสดงเมทริกซ์สองมิติได้อย่างง่ายด้วยอาร์เรย์หนึ่งมิติ ในการแทนแบบ row major order องค์ประกอบในแต่ละแถวของเมทริกซ์จะถูกเก็บในดัชนีอาร์เรย์ตามลำดับ สำหรับเมทริกซ์ mXn สูตรสามารถเขียนได้ดังนี้

matrix[i][j]=array[n*i+j]

ดูสคริปต์ตัวอย่างอีกตัวสำหรับบวกเมทริกซ์ 2 ตัวและพิมพ์เมทริกซ์ผลลัพธ์

#!/bin/bash
read -p "Enter the matrix order [mxn] : " t
m=${t:0:1}
n=${t:2:1}
echo "Enter the elements for first matrix"
for i in `seq 0 $(($m-1))`
do
    for j in `seq 0 $(($n-1))`
    do
        read x[$(($n*$i+$j))]
    done
done
echo "Enter the elements for second matrix"
for i in `seq 0 $(($m-1))`
do
    for j in `seq 0 $(($n-1))`
    do
        read y[$(($n*$i+$j))]
        z[$(($n*$i+$j))]=$((${x[$(($n*$i+$j))]}+${y[$(($n*$i+$j))]}))
    done
done
echo "Matrix after addition is"
for i in `seq 0 $(($m-1))`
do
    for j in `seq 0 $(($n-1))`
    do
        echo -ne "${z[$(($n*$i+$j))]}\t"
    done
    echo -e "\n"
done
exit 0

แม้จะมีข้อจำกัดในการนำอาร์เรย์ไปใช้ในเชลล์สคริปติ้ง แต่มันกลายเป็นประโยชน์ในบางสถานการณ์ โดยเฉพาะเมื่อเราจัดการกับ command substitution มองจากมุมมองผู้ดูแลระบบ แนวคิดของอาร์เรย์ได้ปูทางให้พัฒนาสคริปต์พื้นหลังมากมายในระบบ GNU/Linux