bash
に何かあります
myArray=('red' 'orange' 'green')
そして、私は次のようなことをしたいと思います
echo ${myArray['green']}
この場合、2
。これは達成可能ですか?
これはそれを行います:
#!/bin/bash
my_array=(red orange green)
value='green'
for i in "${!my_array[@]}"; do
if [[ "${my_array[$i]}" = "${value}" ]]; then
echo "${i}";
fi
done
明らかに、これを関数(例えばget_index())に変えると-ジェネリックにすることができます
使用する前に配列を宣言する必要があります
declare -A myArray
myArray=([red]=1 [orange]=2 [green]=3)
echo ${myArray['orange']}
いいえ。bash
の整数を持つ単純な配列にのみインデックスを付けることができます。連想配列(bash
4で導入)は、文字列によってインデックスを付けることができます。ただし、特別に構成された連想配列なしでは、要求するタイプの逆ルックアップには提供されません。
$ declare -A myArray
$ myArray=([red]=0 [orange]=1 [green]=2)
$ echo ${myArray[green]}
2
トリッキーな方法も1つあります。
echo ${myArray[@]/green//} | cut -d/ -f1 | wc -w | tr -d ' '
そして、あなたは2を取得します ここに参考文献があります
私はその解決策が好きです:
let "n=(`echo ${myArray[@]} | tr -s " " "\n" | grep -n "green" | cut -d":" -f 1`)-1"
変数nには結果が含まれます!
これは、chepnerが示したように、連想配列を初期化する別の方法です。 declare
を明示的に、または-A
属性を持つ連想配列をタイプセットする必要があることを忘れないでください。
i=0; declare -A myArray=( [red]=$((i++)) [orange]=$((i++)) [green]=$((i++)) )
echo ${myArray[green]}
2
これにより、値をハードコーディングする必要がなくなり、重複する可能性が低くなります。
追加する値がたくさんある場合は、それらを別々の行に配置すると役立つ場合があります。
i=0; declare -A myArray;
myArray+=( [red]=$((i++)) )
myArray+=( [orange]=$((i++)) )
myArray+=( [green]=$((i++)) )
echo ${myArray[green]}
2
数字と小文字の配列が必要な場合(メニュー選択の場合など)、次のようなこともできます。
declare -a mKeys_1=( {{0..9},{a..z}} );
i=0; declare -A mKeys_1_Lookup; eval mKeys_1_Lookup[{{0..9},{a..z}}]="$((i++))";
次に実行する場合
echo "${mKeys_1[15]}"
f
echo "${mKeys_1_Lookup[f]}"
15
これは配列に対してのみ機能する可能性があり、
my_array=(red orange green)
echo "$(printf "%s\n" "${my_array[@]}")" | grep -n '^orange$' | sed 's/:orange//'
出力:
2
Tsvファイルでヘッダーインデックスを検索する場合は、
head -n 1 tsv_filename | sed 's/\t/\n/g' | grep -n '^header_name$' | sed 's/:header_name//g'
別のトリッキーなワンライナー:
_index=$((-1 + 10#0$(IFS=$'\n' echo "${my_array[*]}" | grep --line-number --fixed-strings -- "$value" | cut -f1 -d:)))
_
特徴:
-1
_を返します警告:
value
が空でないことを要求します実行順に分類することによる説明:
_IFS=$'\n' echo "${my_array[*]}"
_
配列展開セパレーター(IFS
)を改行charに設定し、配列を展開します
_grep --line-number --fixed-strings -- "$value"
_
マッチのgrep:
--line-number
_または_-n
_)--fixed-strings
_または_-F
_;正規表現を無効にします)_-
_で始まる要素を許可する(_--
_)
cut -f1 -d:
行番号のみを抽出します(形式は_<line_num>:<matched line>
_です)
_$((-1 + 10#0$(...)))
_
行番号には1のインデックスが付けられ、配列には0のインデックスが付けられるため、1を引く
$(...)
が一致しない場合:
0
_が使用されます(_10#0
_)$(...)
が一致する場合:10#0
_が付いています。すなわち_10#02
_、_10#09
_、_10#014
_など10#
_プレフィックスは、8進数ではなく10進数/ 10進数を強制しますawk
、grep
およびbash算術演算の代わりにcut
を使用します。
_IFS=$'\n'; awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}" <<< "${my_array[*]}"
_
特徴:
警告:
実行順に分類することによる説明:
_IFS=$'\n' [...] <<< "${my_array[*]}"
_
配列展開セパレーター(IFS
)を改行charに設定し、配列を展開します
_awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}"
_
行全体と一致し、0から始まる行番号を出力します
${value//\"/\\\"}
_は、_$value
_の二重引用符をエスケープバージョンに置き換えますBash 3.xではもう少し簡潔で機能します。
my_array=(red orange green)
value='green'
for i in "${!my_array[@]}"; do
[[ "${my_array[$i]}" = "${value}" ]] && break
done
echo $i
Zshでできること
xs=( foo bar qux )
echo ${xs[(ie)bar]}
zshparam(1)のサブセクションの添え字フラグを参照してください
簡単なソリューション:
my_array=(red orange green)
echo ${my_array[*]} | tr ' ' '\n' | awk '/green/ {print NR-1}'