Czy istnieje dobry sposób sprawdzenia, czy tablica zawiera element w bashu (lepszy niż zapętlanie)?
Alternatywnie, czy istnieje inny sposób sprawdzenia, czy liczba lub ciąg znaków jest równy dowolnemu zestawowi predefiniowanych stałych?
W Bash 4 możesz używać tablic asocjacyjnych:
# set up array of constants
declare -A array
for constant in foo bar baz
do
array[$constant]=1
done
# test for existence
test1="bar"
test2="xyzzy"
if [[ ${array[$test1]} ]]; then echo "Exists"; fi # Exists
if [[ ${array[$test2]} ]]; then echo "Exists"; fi # doesn't
Aby wstępnie skonfigurować tablicę, możesz również wykonać bezpośrednie przypisania:
array[foo]=1
array[bar]=1
# etc.
lub w ten sposób:
array=([foo]=1 [bar]=1 [baz]=1)
${array[$test1]}
jest prosty, ale ma problem: nie zadziała, jeśli użyjesz goset -u
w swoich skryptach (co jest zalecane), ponieważ otrzymasz „niezwiązaną zmienną”.set -u
: davidpashley.com/articles/writing-robust-shell-scripts.html , blog.hashbang0.com/2010/05/18/robust-bash-scripts-part-one , openews.net/2012/bash- niezawodny skrypt-do-zapisu .To stare pytanie, ale myślę, że to, co jest najprostsze rozwiązanie jeszcze nie pojawił:
test ${array[key]+_}
. Przykład:Wyjścia:
Aby zobaczyć, jak to działa, sprawdź to .
źródło
env
aby uniknąć dwuznaczności w aliasach, progach i innych funkcjach, które mogły przyjąć nazwę „test”. Jak wyżejenv test ${xs[a]+_} && echo "a is set"
. Możesz także uzyskać tę funkcjonalność za pomocą podwójnych nawiasów, ta sama sztuczka, a następnie sprawdzenie, czy null:[[ ! -z "${xs[b]+_}" ]] && echo "b is set"
[[ ${xs[b]+set} ]]
Istnieje sposób sprawdzenia, czy istnieje element tablicy asocjacyjnej (nie jest ustawiony), różni się on od pustego:
Następnie użyj go:
źródło
if ! some_check then return 1
=some_check
. Tak:isNotSet() { [[ ... ]] }
. Sprawdź moje rozwiązanie poniżej, możesz to zrobić w prosty sposób.Możesz sprawdzić, czy pozycja jest obecna, przesyłając potokiem zawartość tablicy do grep.
Możesz także uzyskać indeks pozycji za pomocą grep -n, który zwraca numer linii dopasowania (pamiętaj, aby odjąć 1, aby uzyskać indeks zerowy). Będzie to dość szybkie, z wyjątkiem bardzo dużych tablic.
wyjaśnienie:
$( ... )
to to samo, co użycie backsticksa do przechwytywania wyniku polecenia w zmiennejprintf
wypisuje moje dane po jednym elemencie w wierszu@
zamiast*.
tego unika się podziału „witaj świecie” na 2 linie)grep
szuka dokładnego ciągu:^
i$
dopasowuje początek i koniec wierszagrep -n
zwraca wiersz nr, w postaci 4: witaj świeciegrep -m 1
znajduje tylko pierwszy meczcut
wyodrębnia tylko numer wierszaMożesz oczywiście złożyć odejmowanie do polecenia. Ale następnie sprawdź brak -1:
$(( ... ))
robi arytmetykę liczb całkowitychźródło
Nie sądzę, że możesz to zrobić poprawnie bez zapętlania, chyba że masz bardzo ograniczone dane w tablicy.
Oto jeden prosty wariant, to poprawnie powiedziałoby, że
"Super User"
istnieje w tablicy. Ale powiedziałoby to również, że"uper Use"
jest w tablicy.Problem polega na tym, że nie ma łatwego sposobu na dodanie kotwic (które mogę wymyślić) poza zapętlaniem tablicy. Chyba że możesz dodać je przed umieszczeniem ich w tablicy ...
źródło
grep "\b$FINDME\b"
). Prawdopodobnie mógłby pracować ze stałymi niealfanumerycznymi, które nie mają spacji, z"(^| )$FINDME(\$| )"
(lub coś w tym rodzaju ... Nigdy nie byłem w stanie dowiedzieć się, jakiego smaku używa wyrażenie regularne grep.)źródło
in_array
. Na zdrowie${ARRAY[@]}
należy użyć.