BASH: регулярные выражения: =~ и BASH_REMATCH

Автор: | 11/04/2015

terminalВ BASH версии 3.0 и выше имеется специальный оператор для работы с регулярными выражениями =~.

 

Для примера возьмём такой скрипт:

#!/usr/bin/env bash

PATH="/var/lib/mysql/rtfm_db1/*"
regex=".*.MYI"

for file in $PATH; do
    if [[ $file =~ $regex ]]; then
        echo -e "Found file: $file"
    fi
done

Результат:

$ ./reg.sh
Found file: /var/lib/mysql/rtfm_db1/db1_commentmeta.MYI
Found file: /var/lib/mysql/rtfm_db1/db1_comments.MYI
Found file: /var/lib/mysql/rtfm_db1/db1_links.MYI
...
Found file: /var/lib/mysql/rtfm_db1/db1_usermeta.MYI
Found file: /var/lib/mysql/rtfm_db1/db1_users.MYI

Результат проверкирегулярного выржения хранится в переменной BASH_REMATCH. Т.е. скрипт можно переписать так:

#!/usr/bin/env bash

PATH="/var/lib/mysql/rtfm_db1/*"
regex=".*.MYI"

for file in $PATH; do
    if [[ $file =~ $regex ]]; then
        echo -e "Found file: $BASH_REMATCH"
    fi
done

И даже больше – массивом:

#!/usr/bin/env bash

PATH="/var/lib/mysql/rtfm_db1/*"
regex=".*.MYI"

for file in $PATH; do
    if [[ $file =~ $regex ]]; then
        echo -e "Found file: ${BASH_REMATCH[@]}"
    fi
done

В данном случае – массив будет хранить только один элемент:

#!/usr/bin/env bash

PATH="/var/lib/mysql/rtfm_db1/*"
regex=".*.MYI"

for file in $PATH; do
    if [[ $file =~ $regex ]]; then
        # выводим кол-во элемента массива
        echo -e "Found file: ${#BASH_REMATCH[@]}"
    fi
done
$ ./reg.sh
Found file: 1
Found file: 1
Found file: 1

Смысл массива становится более понятен, если мы используем скобки в регулярном выражении для получения (или “захвата”) каких-то данных, например:

#!/usr/bin/env bash

PATH="/var/lib/mysql/rtfm_db1/*"
# добавляем захват значения
regex="db1_(.*).MYI"

for file in $PATH; do
    if [[ $file =~ $regex ]]; then
        # выводим количество элементов массива
        echo -e "Number of BASH_REMATCH array elements: ${#BASH_REMATCH[@]}"
        # вся строка, которая попала под фильтр регулярного выражения - первый (индекс 0) элемент массива
        echo -e "Full capture string: ${BASH_REMATCH[0]}"
        # второй элемент массива (индекс 1) - захваченное () в регулярном выражении значение
        echo -e "Captured string element: ${BASH_REMATCH[1]}"
    fi
done

Результат:

$ ./reg.sh
Number of BASH_REMATCH array elements: 2
Full capture string: db1_commentmeta.MYI
Captured string element: commentmeta
...
Number of BASH_REMATCH array elements: 2
Full capture string: db1_users.MYI
Captured string element: users