2017-07-27 16 views
0

私は、どこで実行されたかによって異なるコードビットを使用する必要のある洗練されたスクリプトを持っています。bashの文字列の配列

これは動的に決定する良い方法ではなく、実行時にハードコードして参照する必要があります。私は、私は必要だと思う何

は、その後、私は何とか

はルビーでは、これは同じくらい簡単になり、その値はスクリプト実行プログラムのホスト名の値が含まれているキーを見つけるために照会することができ、この

{ 
"location": { 
    "type1": [ "hostname1", "hostname2", "hostname 3" ], 
    "type2": [ "hostname4, "hostname5", "hostname6"], 
    "type3": [ "hostname7, "hostname8", "hostname9"] 
    } 
} 

case $array[$(hostname)] in #pseudocode 
    type1) bash $dir/type1.sh;; 
    type2) bash $dir/type2.sh;; 
    *) bash $dir/type3.sh;; 
esac 

のようなものですハッシュを作成して値を参照することです。 これはbashで可能ですか?とにかく、スクリプトにハードコーディングすることになるだろう場合は、caseを使用して、単純に考える

hash.key(Socket.gethostname) 
+0

Waitaminute。あなたはホストかタイプによって検索していますか?あなたの疑似コードは前者を表していますが、あなたの辞書は後者のために作成されています。 –

答えて

3

case $(hostname) in 
    (hostname1|hostname2|hostname3) bash "$dir/type1.sh";; 
    (hostname4|hostname5|hostname6) bash "$dir/type2.sh";; 
    (*) bash "$dir/type3.sh";; 
esac 
+0

あなたはこれがもっとスマートで、ずっと簡単だと分かっています。それを指摘してくれてありがとう。 –

+0

引用符を修正すると、他の答えの下のコメントに指摘されているように、良い解決策が得られます。 –

+0

引用符とスペース/インデントを修復しました。デビッドとチャールズの指摘のおかげで! –

3

あなたはbashで文字列の配列を格納することができ、あなたはbashでマップを保存することができますが、配列をマップの値として格納することはできません。

ただし、型名がシェル変数名で有効な文字のみを使用する場合は、各配列を別の変数に格納し、間接参照を使用して変数名をルックアップまたは反復することで不正行為を行うことができます。上記に定義して

#!/bin/bash 

[[ $BASH_VERSION ]] && ! [[ $BASH_VERSION =~ ^([0123][.]|4[.][012]) ]] || { 
    echo "This requires bash 4.3 or later" >&2 
    exit 1 
} 

# we're declaring any variable name starting with loc_ to be part of our data 
loc_type1=("hostname1" "hostname2" "hostname3") 
loc_type2=("hostname4" "hostname5" "hostname6") 
loc_type3=(etc etc etc) 

# map from type to hostnames; "hosts_for_type type1" will emit hostnames 1-3 
hosts_for_type() { 
    local -n type_arr="loc_$1" 
    printf '%s\n' "${type_arr[@]}" 
} 

# do the heavy lifting to build a map from hostnames to types 
# this only needs to be run once for the given data 
declare -g -A type_for_host=() 
build_hosttype_map() { 
    local varname typename host 

    # abort if inverse map is already built so this only runs once 
    ((${#type_for_host[@]})) && return 

    for varname in "${[email protected]}"; do 
    declare -n locarr="$varname" 
    typename=${varname#loc_} 
    for host in "${locarr[@]}"; do 
     type_for_host[$host]=$typename 
    done 
    done 
} 

# map from hostname to type; uses inverse map built above. 
type_for_host() { 
    build_hosttype_map 
    printf '%s\n' "${type_for_host[$1]}" 
} 

$ type_for_host hostname1 
type1 
$ hosts_for_type type1 
hostname1 
hostname2 
hostname3 

(あなたはすべての可能な文字を含むデータ要素を処理する場合は、'%s\n'フォーマット文字列を変更することで、NULsに改行区切り文字から切り替えたいですよただし、入力ドメインが現在有効なホスト名で構成されているため、すぐには呼び出されません。

+0

ああ、それは私が予想していたよりも醜いです。私は本当にこれに入った努力に感謝します。 –

+3

Heh。構文上の醜さと概念的な醜さの間には大きな違いがあります。ここには多くの構文がありますが、実行時環境、データなどに関係なく一貫した方法で動作するように定義された構文です(予約済みの変数名前空間をもちろん 'loc_'という接頭辞)。これは、「$(find ...)」のファイルのようなものと比べて、見た目がひどくはありませんが、実際に実行時に何をするのかという点で、コーナーケースや醜いものでいっぱいです。 –

+1

「$ dir/type1.sh」は予期しない動作をするでしょう。ディレクトリ名に空白が含まれているか、 'IFS'値にその名前の文字が含まれています('/'など)。 '' $ dir '/ type1.sh'(または '' $ dir/type1.sh' '')が前提条件や警告なしで正しいものである必要があります。 –