75

私は何かがbash好きです

myArray=('red' 'orange' 'green')

そして、私は次のようなことをしたいです

echo ${myArray['green']}

この場合、これはを出力します2。これは達成可能ですか?

4

17 に答える 17

93

これはそれを行います:

#!/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()など)に変換すると、汎用的にすることができます

于 2013-02-22T16:30:09.900 に答える
34

で使用する前に配列を宣言する必要があります

declare -A myArray
myArray=([red]=1 [orange]=2 [green]=3)
echo ${myArray['orange']}
于 2013-02-22T16:32:01.657 に答える
16

いいえ。インデックスを作成できるのは、整数の単純な配列のみですbash。連想配列(bash4で導入)は、文字列でインデックスを付けることができます。ただし、特別に構築された連想配列がなければ、要求しているタイプの逆ルックアップには対応していません。

$ declare -A myArray
$ myArray=([red]=0 [orange]=1 [green]=2)
$ echo ${myArray[green]}
2
于 2013-02-22T16:28:14.557 に答える
16

トリッキーな方法も1つあります。

echo ${myArray[@]/green//} | cut -d/ -f1 | wc -w | tr -d ' '

そして、あなたは2を取得します ここに参照があります

于 2015-06-17T15:00:09.263 に答える
7

もう少し簡潔で、Bash3.xで機能します。

my_array=(red orange green)
value='green'

for i in "${!my_array[@]}"; do
   [[ "${my_array[$i]}" = "${value}" ]] && break
done

echo $i
于 2018-05-23T06:39:20.427 に答える
5

もう1つのトリッキーなワンライナー:

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)を改行文字に設定し、配列を展開します

grep --line-number --fixed-strings -- "$value"

一致するgrep:

  • 行番号を表示する(--line-numberまたは-n
  • 固定文字列を使用する(--fixed-stringsまたは-F;正規表現を無効にする)
  • ---)で始まる要素を許可する

    カット-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進数を強制します


、&​​bash演算awkの代わりに使用:grepcut

IFS=$'\n'; awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}" <<< "${my_array[*]}"

特徴:

  • スペースのある要素をサポート
  • 空の要素をサポート
  • サブシェルで開かれるコマンドが少ない

警告:

  • 見つからない場合は戻ります

実行順に分解して説明します。

IFS=$'\n' [...] <<< "${my_array[*]}"

配列展開区切り文字(IFS)を改行文字に設定し、配列を展開します

awk "\$0 == \"${value//\"/\\\"}\" {print NR-1}"

行全体を一致させ、0インデックスの行番号を出力します

  • ${value//\"/\\\"}$valueの二重引用符をエスケープされたバージョンに置き換えます
  • 変数の置換が必要なため、このセグメントには必要以上のエスケープがあります
于 2019-01-03T08:48:45.617 に答える
3

これはアレイに対してのみ機能する可能性がありますが、

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'
于 2017-04-12T11:28:47.500 に答える
2

私はその解決策が好きです:

let "n=(`echo ${myArray[@]} | tr -s " " "\n" | grep -n "green" | cut -d":" -f 1`)-1"

変数nには結果が含まれます!

于 2015-08-13T18:08:54.477 に答える
2

これは、chepnerが示したように、連想配列を初期化するもう1つの方法です。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
于 2015-11-15T20:01:49.153 に答える
0

zshでは次のことができます

xs=( foo bar qux )
echo ${xs[(ie)bar]}

zshparam(1)サブセクションの添え字フラグを参照してください。

于 2017-06-18T04:02:16.833 に答える
0

これにより、クエリの0ベースの配列インデックス(ここでは「オレンジ」)が出力されます。

echo $(( $(printf "%s\n" "${myArray[@]}" | sed -n '/^orange$/{=;q}') - 1 ))

クエリが配列で発生しない場合は、上記の出力が表示されます-1

クエリが配列内で複数回発生する場合、上記はクエリの最初の発生のインデックスを出力します。

このソリューションはsedを呼び出すため、このスレッドの純粋なbashソリューションのいくつかと効率的に競合できるとは思えません。

于 2020-05-15T12:16:10.317 に答える
0

これは、配列メンバーのインデックスを返すためのいくつかのメソッドを示しています。配列は、最初と最後のインデックスに適用できない値を使用して、1から始まるインデックスを提供し、制限を提供します。

whileループは、配列値のインデックスを生成する目的で、カットオフを使用した反復の興味深い方法です。ループの本体には、null操作のコロンのみが含まれます。重要な部分は、一致するまで、または可能な一致を過ぎてiを繰り返すことです。

関数indexof()は、テキスト値をインデックスに変換します。値が一致しない場合、関数はエラー処理を実行するためのテストで使用できるエラーコードを返します。配列に一致しない入力値は、範囲制限(-gt, -lt)テストを超えます。

良い/悪い値をループするテスト(メインコード)があり、最初の3行はコメント化されていますが、興味深い結果を確認するためにいくつかのバリエーションを試してください(lines 1,3 or 2,3 or 4)。エラー状態を考慮したコードをいくつか含めました。これは便利な場合があるためです。

コードの最後の行は、インデックス値をエコーする既知の適切な値「緑」で関数indexofを呼び出します。

indexof(){
  local s i;

  #   0    1   2     3    4
  s=( @@@ red green blue @o@ )

  while [ ${s[i++]} != $1 ] && [ $i -lt ${#s[@]} ]; do :; done

  [ $i -gt 1 ] && [ $i -lt ${#s[@]} ] || return

  let i--

  echo $i
};# end function indexof

# --- main code ---
echo -e \\033c
echo 'Testing good and bad variables:'
for x in @@@ red pot green blue frog bob @o@;
do
  #v=$(indexof $x) || break
  #v=$(indexof $x) || continue
  #echo $v
  v=$(indexof $x) && echo -e "$x:\t ok" || echo -e "$x:\t unmatched"
done 

echo -e '\nShow the index of array member green:'
indexof green
于 2020-08-03T01:22:00.120 に答える
0
myArray=('red' 'orange' 'green')
echo ${myArray[@]}
arrayElementToBeRemoved='orange'
echo "removing element: $arrayElementToBeRemoved"
# Find index of the array element (to be kept or preserved)
let "index=(`echo ${myArray[@]} | tr -s " " "\n" | grep -n "$arrayElementToBeRemoved" | cut -d":" -f 1`)-1"
unset "myArray[$index]"
echo ${myArray[@]}
于 2020-09-22T00:50:35.907 に答える
0

私は自分に似たものが欲しかったので、ループを避けて、思いついた...

myArray=('red' 'orange' 'green')
declare -p myArray | sed -n "s,.*\[\([^]]*\)\]=\"green\".*,\1,p"

...要素が見つからない場合にstdoutを汚さないままにします...

$ myArray=('red' 'orange' 'green')
$ declare -p myArray | sed -n "s,.*\[\([^]]*\)\]=\"green\".*,\1,p"
2

$ declare -p myArray | sed -n "s,.*\[\([^]]*\)\]=\"gren\".*,\1,p"
$

その後、私はグーグルで検索し、この質問を見つけて、共有したいと思いました;)

于 2021-01-11T19:04:08.527 に答える
0

これは、キャラクター「モリー」の1ベースのNEUROMANCERインデックスを出力します;)

get_index() {

  declare -n dummy_array="$1"
  # alternative: split read -ra array <<< "${dummy_array[@]}"
  local array=( "${dummy_array[@]}" )
  # alternative: local value; value="$( for dummy_value; do true; done; echo "$dummy_value" )"
  local value=$2
  local length="${#array[@]}"
  local i=0
  
  while (( i < length ))
  do
    if [ "${array[$i]}" = "$value" ]
    then echo $(( i + 1 )); return 0
    fi; (( i++ ))
  done
  
  echo "$2 not found beneath $1"
  exit 1

}

NEUROMANCER=(Case Molly Riviera)
get_index NEUROMANCER Molly
get_index NEUROMANCER 'John Doe'

次に実行する場合:

$ bash script.sh
2
John Doe not found beneath NEUROMANCER

于 2021-11-09T22:26:29.397 に答える
0
function array_indexof() {
  [ $# -lt 2 ] && return 1
  local a=("$@")
  local v="${a[-1]}"
  unset a[-1]
  local i
  for i in ${!a[@]}; do
    if [ "${a[$i]}" = "$v" ]; then
      echo $i
      return 0 # stop after first match
    fi
  done
  return 1
}

a=(a b c d)
i=$(array_indexof "${a[@]}" d)
echo $i # 3
于 2022-01-20T21:34:23.003 に答える
-2

簡単な解決策:

my_array=(red orange green)
echo ${my_array[*]} | tr ' ' '\n' | awk '/green/ {print NR-1}'
于 2019-03-02T10:20:41.550 に答える