Bagaimana cara port ke array bash-style ke ash?

13

Beberapa waktu lalu saya telah menulis skrip bash yang sekarang harus dapat dijalankan di lingkungan ash.

Di bashdalamnya seperti:

services=( "service1.service"
           "service2.service"                                       
           "service3.service" )  

for service in "${services[@]}"
do
   START $service                   
done

START()
{
   echo "Starting "$1
   systemctl start $1
}

Pada kenyataannya ada seperti 40 layanan dalam array, dan saya ingin membuat transisi ini tanpa rasa sakit dan sebersih mungkin. Selalu menggunakan bashisme. Sekarang saya dalam keadaan darurat dengan tugas untuk membuat skrip lebih portabel.

Untuk alasan portabilitas mungkin akan lebih baik untuk memiliki ashsolusi murni . Tetapi karena saya memiliki yang cukup kuat busyboxdi pembuangan saya, saya mungkin mengorbankan portabilitas. Hanya jika keterbacaan meningkat banyak, karena skrip "bersih" juga metrik.

Apa solusi yang portabel dan bersih dalam kasus ini?

bermetamorfosis
sumber

Jawaban:

8

Sebelum array berada di bash,, kshdan cangkang lainnya, metode yang biasa digunakan adalah memilih pembatas yang tidak ada di salah satu elemen (atau yang tidak biasa untuk meminimalkan melarikan diri yang diperlukan), dan beralih ke string yang berisi semua elemen, dipisahkan oleh pembatas itu. Whitespace biasanya merupakan pilihan pembatas yang paling nyaman karena shell sudah membagi "kata" dengan whitespace secara default (Anda dapat mengatur IFS jika Anda ingin membagi pada sesuatu yang berbeda).

Sebagai contoh:

# backslash-escape any non-delimiter whitespace and all other characters that
# have special meaning to the shell, e.g. globs, parenthesis, ampersands, etc.
services='service1.service service2.service service3.service'

for s in $services ; do  # NOTE: do not double-quote $services here.
  START "$s"
done

$servicesseharusnya TIDAK dikutip ganda di sini karena kami ingin shell membaginya menjadi "kata-kata".

cas
sumber
3

abu tidak memiliki array. Satu-satunya hal yang mendekati adalah parameter posisi, sehingga Anda bisa melakukannya

set -- "service1.service" \
       "service2.service" \
       "service3.service"

for service in "$@"
do
   START $service
done
glenn jackman
sumber
3

Jika Anda perlu merujuk ke daftar layanan hanya sekali, Anda dapat menggunakan di sini-doc:

while IFS= read -r service
do
   START "$service"
done << END
service1.service
service2.service
service3.service
END

Perhatikan bahwa nama layanan tidak boleh dikutip dalam daftar (walaupun "$service"mungkin harus dikutip, kecuali Anda memiliki alasan yang baik untuk tidak melakukannya). Jika Anda ingin membuat indentasi nama layanan, gunakan <<-alih-alih <<dan beri indentasi nama dengan tab:

while IFS= read -r service
do
   START "$service"
done <<- END
        service1.service
        service2.service
        service3.service
END
Scott
sumber