Câu trả lời:
Trong Bash 4, bạn có thể sử dụng mảng kết hợp:
# 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
Để thiết lập mảng ban đầu, bạn cũng có thể thực hiện các bài tập trực tiếp:
array[foo]=1
array[bar]=1
# etc.
hoặc theo cách này:
array=([foo]=1 [bar]=1 [baz]=1)
${array[$test1]}
đơn giản nhưng có một vấn đề: nó sẽ không hoạt động nếu bạn sử dụng set -u
trong các tập lệnh của mình (được khuyến nghị), vì bạn sẽ nhận được "biến không liên kết".
Đó là một câu hỏi cũ, nhưng tôi nghĩ giải pháp đơn giản nhất chưa xuất hiện là gì : test ${array[key]+_}
. Thí dụ:
declare -A xs=([a]=1 [b]="")
test ${xs[a]+_} && echo "a is set"
test ${xs[b]+_} && echo "b is set"
test ${xs[c]+_} && echo "c is set"
Đầu ra:
a is set
b is set
env
để tránh sự mơ hồ trong bí danh, pross và các chức năng khác có thể đã áp dụng tên "thử nghiệm". Như trên env test ${xs[a]+_} && echo "a is set"
. Bạn cũng có thể có được chức năng này bằng cách sử dụng dấu ngoặc kép, cùng một mẹo sau đó kiểm tra null:[[ ! -z "${xs[b]+_}" ]] && echo "b is set"
[[ ${xs[b]+set} ]]
Có một cách để kiểm tra nếu một phần tử của mảng kết hợp tồn tại (không được đặt), điều này khác với trống:
isNotSet() {
if [[ ! ${!1} && ${!1-_} ]]
then
return 1
fi
}
Sau đó sử dụng nó:
declare -A assoc
KEY="key"
isNotSet assoc[${KEY}]
if [ $? -ne 0 ]
then
echo "${KEY} is not set."
fi
if ! some_check then return 1
= some_check
. Vì vậy : isNotSet() { [[ ... ]] }
. Kiểm tra giải pháp của tôi dưới đây, bạn có thể làm điều đó trong một kiểm tra đơn giản.
Bạn có thể xem nếu một mục có mặt bằng cách chuyển nội dung của mảng sang grep.
printf "%s\n" "${mydata[@]}" | grep "^${val}$"
Bạn cũng có thể lấy chỉ mục của mục nhập bằng grep -n, trả về số dòng của một trận đấu (nhớ trừ 1 để lấy chỉ số dựa trên số 0) Điều này sẽ nhanh chóng hợp lý trừ các mảng rất lớn.
# given the following data
mydata=(a b c "hello world")
for val in a c hello "hello world"
do
# get line # of 1st matching entry
ix=$( printf "%s\n" "${mydata[@]}" | grep -n -m 1 "^${val}$" | cut -d ":" -f1 )
if [[ -z $ix ]]
then
echo $val missing
else
# subtract 1. Bash arrays are zero-based, but grep -n returns 1 for 1st line, not 0
echo $val found at $(( ix-1 ))
fi
done
a found at 0
c found at 2
hello missing
hello world found at 3
giải trình:
$( ... )
cũng giống như sử dụng backticks để bắt đầu ra của lệnh thành một biến printf
xuất ra mydata một phần tử trên mỗi dòng @
thay vì *.
điều này tránh việc chia "hello world" thành 2 dòng)grep
tìm kiếm chuỗi chính xác: ^
và $
khớp đầu và cuối dònggrep -n
trả về dòng #, dưới dạng 4: xin chào thế giới grep -m 1
chỉ tìm thấy trận đấu đầu tiêncut
chỉ trích xuất số dòng Tất nhiên bạn có thể gấp phép trừ vào lệnh. Nhưng sau đó kiểm tra -1 cho thiếu:
ix=$(( $( printf "%s\n" "${mydata[@]}" | grep -n -m 1 "^${val}$" | cut -d ":" -f1 ) - 1 ))
if [[ $ix == -1 ]]; then echo missing; else ... fi
$(( ... ))
không số học số nguyênTôi không nghĩ rằng bạn có thể làm điều đó đúng mà không cần lặp trừ khi bạn có dữ liệu rất hạn chế trong mảng.
Đây là một biến thể đơn giản, điều này sẽ nói chính xác rằng "Super User"
tồn tại trong mảng. Nhưng nó cũng sẽ nói rằng đó "uper Use"
là trong mảng.
MyArray=('Super User' 'Stack Overflow' 'Server Fault' 'Jeff' );
FINDME="Super User"
FOUND=`echo ${MyArray[*]} | grep "$FINDME"`
if [ "${FOUND}" != "" ]; then
echo Array contains: $FINDME
else
echo $FINDME not found
fi
#
# If you where to add anchors < and > to the data it could work
# This would find "Super User" but not "uper Use"
#
MyArray2=('<Super User>' '<Stack Overflow>' '<Server Fault>' '<Jeff>' );
FOUND=`echo ${MyArray2[*]} | grep "<$FINDME>"`
if [ "${FOUND}" != "" ]; then
echo Array contains: $FINDME
else
echo $FINDME not found
fi
Vấn đề là không có cách dễ dàng để thêm các neo (mà tôi có thể nghĩ ra) ngoài việc lặp qua mảng. Trừ khi bạn có thể thêm chúng trước khi bạn đặt chúng vào mảng ...
grep "\b$FINDME\b"
). Có lẽ có thể làm việc với các hằng số không phải là chữ và số không có khoảng trắng, với "(^| )$FINDME(\$| )"
(hoặc một cái gì đó tương tự ... Tôi chưa bao giờ có thể tìm hiểu hương vị của regrec grep sử dụng.)
#!/bin/bash
function in_array {
ARRAY=$2
for e in ${ARRAY[*]}
do
if [[ "$e" == "$1" ]]
then
return 0
fi
done
return 1
}
my_array=(Drupal Wordpress Joomla)
if in_array "Drupal" "${my_array[*]}"
then
echo "Found"
else
echo "Not found"
fi
in_array
. Chúc mừng
${ARRAY[@]}
nên được sử dụng.