Wie kann man Arrays im Bash-Stil auf Asche portieren?


11

Vor einiger Zeit habe ich ein Bash-Skript geschrieben, das jetzt in einer Umgebung mit ausgeführt werden kann ash.

Darin bashwar wie:

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

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

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

In Wirklichkeit gibt es ungefähr 40 Dienste im Array, und ich möchte diesen Übergang so schmerzlos und sauber wie möglich gestalten. Ich habe immer bashIsmen benutzt. Jetzt bin ich in der Klemme mit der Aufgabe, Skripte portabler zu machen.

Aus Gründen der Portabilität wäre es wahrscheinlich schön, eine reine ashLösung zu haben . Aber da ich einen ziemlich robusten busyboxzur Verfügung habe, könnte ich etwas Portabilität opfern. Nur wenn sich die Lesbarkeit stark verbessert, da "sauberes" Skript ebenfalls eine Metrik ist.

Was wäre in diesem Fall eine tragbare und saubere Lösung?

Antworten:


7

Bevor Arrays waren bash, kshund andere Schalen, war das übliche Verfahren ein Trennzeichen auszuwählen , die nicht in einem der Elemente war (oder eine , die eine erforderliche entweichenden zu minimieren unüblich war) und iterieren über einen String alle Elemente enthält, durch dieses Trennzeichen getrennt. Leerzeichen sind normalerweise die bequemste Trennzeichenoption, da die Shell "Wörter" standardmäßig bereits durch Leerzeichen aufteilt (Sie können IFS festlegen, wenn es auf etwas anderes aufgeteilt werden soll).

Beispielsweise:

# 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

$servicessollte NICHT werden hier in doppelten Anführungszeichen , denn wir wollen die Schale spalten es in „Worte“.


3

Asche hat keine Arrays. Das einzige, was nahe kommt, sind die Positionsparameter, die Sie tun können

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

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

3

Wenn Sie nur einmal auf die Liste der Dienste verweisen müssen, können Sie ein here-doc verwenden:

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

Beachten Sie, dass die Dienstnamen nicht in der Liste angegeben werden sollten (obwohl sie "$service"wahrscheinlich angegeben werden sollten, es sei denn, Sie haben einen guten Grund, dies nicht zu tun). Wenn Sie möchten, dass die Dienstnamen eingerückt werden, verwenden Sie <<-anstelle von <<und rücken Sie die Namen mit Registerkarten ein:

while IFS= read -r service
do
   START "$service"
done <<- END
        service1.service
        service2.service
        service3.service
END
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.