Як портувати до масивів у стилі bash для попелу?


13

Деякий час тому я написав скрипт bash, який тепер повинен мати можливість працювати в середовищі ash.

У bashце було як:

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

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

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

Насправді в наборі є 40 послуг, і я хочу зробити цей перехід максимально безболісним та чистим. Завжди використовували bashIsms. Зараз я перебуваю в глибокій мірі із завданням зробити сценарії більш портативними.

З причини переносимості, напевно, було б непогано мати чисте ashрішення. Але оскільки у мене є досить надійний, busyboxя можу пожертвувати певною портативністю. Тільки якщо читабельність значно покращиться, оскільки "чистий" сценарій теж є показником.

Яке в цьому випадку було б портативне та чисте рішення?

Відповіді:


8

Перед тим як масиви були bash, kshі інші оболонки, звичайний метод був вибрати роздільник , який не був ні в одному з елементів (або той , який був рідкістю , щоб звести до мінімуму будь-яких необхідних втечі), і ітерація над рядком , що містить всі елементи, розділений цим роздільником. Пробіл зазвичай є найзручнішим вибором роздільника, оскільки оболонка вже розбиває «слова» на пробіли за замовчуванням (ви можете встановити IFS, якщо ви хочете, щоб він розділився на щось інше).

Наприклад:

# 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

$servicesповинні НЕ бути в подвійних лапках, тому що ми хочемо оболонки , щоб розділити його на «слова».


3

зола не має масивів. Єдине, що наближається - це позиційні параметри, щоб ви могли це зробити

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

for service in "$@"
do
   START $service
done

3

Якщо вам потрібно звернутися до списку послуг лише один раз, ви можете скористатися тут-документом:

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

Зауважте, що назви служб не повинні цитуватись у списку (хоча, "$service"ймовірно, слід цитувати, якщо у вас немає вагомих причин цього не робити). Якщо ви хочете, щоб імена служб були відступними, використовуйте <<-замість них <<і відступайте від них на вкладках:

while IFS= read -r service
do
   START "$service"
done <<- END
        service1.service
        service2.service
        service3.service
END
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.