web-dev-qa-db-ja.com

ashにbashスタイルの配列に移植する方法は?

少し前に、ashを使用して環境で実行できるはずのbashスクリプトを作成しました。

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を持っているので、移植性を犠牲にするかもしれません。 「クリーン」スクリプトもメトリックであるため、読みやすさが大幅に向上する場合にのみ。

この場合、portableおよびcleanソリューションは何でしょうか?

12
metamorphling

配列がbashksh、およびその他のシェルに入る前は、通常の方法は、要素のいずれにもない区切り文字(または必要なエスケープを最小限に抑えるために一般的ではない区切り文字)を選択することでした)、区切り文字で区切られたすべての要素を含む文字列を反復処理します。シェルはデフォルトで空白文字によって「単語」をすでに分割しているため、通常は空白文字が最も便利な区切り文字の選択です(別のものに分割する場合は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[〜#〜] not [〜#〜]ここで二重引用符で囲む必要がありますwantシェルが「単語」に分割するためです。

8
cas

ashには配列がありません。接近するのは位置パラメータだけなので、次のことができます

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

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

サービスのリストを一度だけ参照する必要がある場合は、ヒアドキュメントを使用できます。

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
3
Scott