Jak przenieść do tablic typu bash na popiół?


13

Jakiś czas temu napisałem skrypt bash, który powinien być teraz w stanie działać w środowisku ash.

W bashtym było jak:

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

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

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

W rzeczywistości w tablicy jest około 40 usług i chcę, aby przejście to było jak najbardziej bezbolesne i czyste. Zawsze bashużywałem isms. Teraz mam problem z tym, aby skrypty były bardziej przenośne.

Ze względu na przenośność prawdopodobnie dobrze byłoby mieć czyste ashrozwiązanie. Ale ponieważ mam do dyspozycji dość solidny sprzęt, busyboxmogę poświęcić pewną przenośność. Tylko wtedy, gdy poprawia się czytelność, ponieważ „czysty” skrypt jest również miernikiem.

Co byłoby przenośnym i czystym rozwiązaniem w tym przypadku?

Odpowiedzi:


8

Przed matryce były bash, kshi inne powłoki, zwykle metodą było wybrać ogranicznik, który nie jest w każdym z elementów (a, który był niczym niezwykłym, aby zminimalizować wszelkie wymagane ucieczki) i iteracyjne łańcucha zawierającego wszystkie elementy, oddzielone tym ogranicznikiem. Biała spacja jest zwykle najwygodniejszym wyborem ogranicznika, ponieważ powłoka domyślnie już dzieli „słowa” za pomocą białych znaków (możesz ustawić IFS, jeśli chcesz, aby dzielił się na coś innego).

Na przykład:

# 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

$servicesNależy NIE być podwójnie cytowany tutaj, ponieważ chcemy powłoka podzielić ją na „słów”.


3

popiół nie ma tablic. Jedyne, co się zbliża, to parametry pozycyjne, więc możesz to zrobić

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

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

3

Jeśli potrzebujesz odwołać się do listy usług tylko raz, możesz skorzystać z dokumentu tutaj:

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

Zauważ, że nazwy usług nie powinny być cytowane na liście (chociaż "$service"prawdopodobnie powinny być cytowane, chyba że masz dobry powód, aby tego nie robić). Jeśli chcesz, aby nazwy usług były wcięte, użyj ich <<-zamiast <<i wcięć za pomocą tabulatorów:

while IFS= read -r service
do
   START "$service"
done <<- END
        service1.service
        service2.service
        service3.service
END
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.