Я хотел бы создать массив, как показано ниже, чтобы проверить, совпадает ли имя выходного файла с шаблоном в массиве.

declare -a arr=('class*_1n_*000000.txt','class*_1n_*010000.txt','class*_2n_*010000.txt','class*_2n_*012000.txt','class*_3n_*235000.txt')

if [[ "${arr[*]}"==$output_filename ]]; then
   echo $output_filename exist in arr
   #do something...
else
   echo $output_filename not exist in arr
   #do something...
fi

Я пробовал следующие 3 случая, и комментарий был бы моим ожидаемым результатом

output_filename='class_2n_20180922012000.txt' #exist
output_filename='classA_2n_20180923012000.txt' #exist
output_filename='classA_4n_20180923012000.txt' #not exist

Но все три случая возврата существуют.

Как я могу решить эту проблему?

Любая помощь была бы весьма признательна :)

1
JC234 22 Сен 2018 в 09:13

1 ответ

Лучший ответ

Хорошо, давайте сначала исправим пару основных проблем синтаксиса оболочки. Объявление массива:

declare -a arr=('class*_1n_*000000.txt','class*_1n_*010000.txt','class*_2n_*010000.txt','class*_2n_*012000.txt','class*_3n_*235000.txt')

Не работает, потому что bash не использует запятые для разделения элементов массива, он использует пробелы. Поскольку в нем нет пробелов, оболочка будет рассматривать его как один большой элемент массива, который содержит некоторые запятые. Вы хотите это:

declare -a arr=('class*_1n_*000000.txt' 'class*_1n_*010000.txt' 'class*_2n_*010000.txt' 'class*_2n_*012000.txt' 'class*_3n_*235000.txt')

Во-вторых, сравнение:

if [[ "${arr[*]}"==$output_filename ]]; then

Ничего не делает так, как вы хотите. Опять же, пробел является разделителем в синтаксисе оболочки, и, поскольку вокруг него нет пробелов, == не рассматривается как оператор, это просто часть одной длинной строки. И [[ somestring ]] проверяет, не является ли строка непустой, и, поскольку эта строка не пуста, проверка всегда оказывается истинной. Теперь очевидное исправление для этого:

if [[ "${arr[*]}" == $output_filename ]]; then

... по крайней мере, делает сравнение, но не сравнение, которое вы хотите. Он обрабатывает все содержимое массива (со всеми элементами, склеенными вместе с пробелами между ними, потому что это то, что делает [*]) как одну строку и проверяет, соответствует ли оно $output_filename, где $output_filename рассматривается как подстановочный знак. Но вы хотели, чтобы элементы массива обрабатывались как шаблоны подстановки, поэтому вам нужно отменить его:

if [[ "$output_filename" == ${arr[*]} ]]; then

... но это по-прежнему не то, что вам нужно, потому что он проверяет, совпадает ли $output_filename со всеми записями в arr, склеенных вместе. Для совпадения $output_filename должен быть список из пяти имен файлов, разделенных пробелами, с первым совпадением class*_1n_*000000.txt, вторым совпадением class*_1n_*010000.txt и т. Д. сравнивайте имя файла с каждым из элементов массива по одному и отслеживайте, нашли ли вы совпадение. Что-то вроде этого:

found_match="false"
for pattern in "${arr[@]}"; do
    if [[ "$output_filename" == $pattern ]]; then
        found_match="true"
        break
    fi
done
if [[ "$found_match" == true ]]; then
   echo "$output_filename exist in arr"
   #do something...
else
   echo "$output_filename not exist in arr"
   #do something...
fi

Обратите внимание, что "${arr[@]}" (обратите внимание на двойные кавычки и @) расширяется до каждого элемента массива, при этом каждый рассматривается как отдельная строка (поэтому for будет перебирать их). Кроме того, строки, которые нужно напечатать, заключаются в двойные кавычки; вам почти всегда нужны двойные кавычки вокруг ссылок на переменные (или вещей, содержащих ссылки на переменные), чтобы избежать неожиданного раскрытия подстановочных знаков и т.п. Однако здесь есть исключение: в [[ "$output_filename" == $pattern ]] $pattern нужно оставить без кавычек, чтобы он обрабатывался как шаблон подстановки, а не фиксированная строка.

3
Gordon Davisson 22 Сен 2018 в 08:16