четверг, 28 марта 2013 г.

Сравнение значения переменной с regex в bash старше 3.1.x

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

#!/bin/bash
int_value=-123

if [[ ! "$int_value" =~ "^-?[0-9]+$" ]]; then
    echo "You specified not integer value: $int_value"
else
    echo "Integer value: $int_value"
fi

Странность заключалась в том, что код выдавал ошибку для вполне целочисленных значений.

$ bash ./test.sh
You specified not integer value: -123

А если запустить его через zsh, то все работало верно:

$ zsh ./test.sh
Integer value: -123

В принципе можно было заменить код на

#!/bin/bash
int_value=-123

if echo "$int_value" | grep -qE '^-?[0-9]+$'; then
    echo "Integer value: $int_value"
else
    echo "You specified not integer value: $int_value"
fi

и успокоиться, но спортивный интерес перевесил и я решил разобраться в причине.

Все стало на свои места после прочтения топика на stackoverflow. Оказывается в bash 3.2 поменяли поведение квотинга при сравнении с regex выражениями и теперь квотить не нужно (более того, старый вариант теперь работает неверно). Чтобы вернуть совместимость с кодом на bash 3.1, нужно либо выставить флаг совместимости compat31, либо исправить код, убрав квотирование

#!/bin/bash
int_value=-123

if [[ ! $int_value =~ ^-?[0-9]+$ ]]; then
    echo "You specified not integer value: $int_value"
else
    echo "Integer value: $int_value"
fi

Если переписывать много кода лень, то можно просто выставить опцию совместимости

#!/bin/bash

setopt compat31
int_value=-123

if [[ ! "$int_value" =~ "^-?[0-9]+$" ]]; then
    echo "You specified not integer value: $int_value"
else
    echo "Integer value: $int_value"
fi

Комментариев нет:

Отправить комментарий