Bash - создать массив с элементами подстановки для сопоставления - PullRequest
0 голосов
/ 22 сентября 2018

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

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 Ответ

0 голосов
/ 22 сентября 2018

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

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 должен быть оставлен без кавычек, поэтому он рассматривается как шаблон с подстановочными знаками, а не как фиксированная строка.

...