Это синтаксически неверно:
#!/usr/bin/env bash
dimension="4x5"
if [[ "$dimension" !=~ '[0-9]x[0-9]' ]]; then
echo 'wtf meng, the dimension needs an "x" in it.'
return 1;
fi
вышеприведенный код имеет плохой синтаксис... поэтому мой вопрос - есть ли способ сделать!=~
...Я предполагаю, что это !~
? Если это правда, то вот вам и правила отрицания, лол. Ладно, я проверил, и !~
тоже не работает..
решение1
Для ключевого слова нет операторов !=~
or . Вместо этого отмените результат сравнения:!~
[[
[[ ! "string" =~ regex ]]
Относительно цитирования regex
аргумента в руководстве говорится:
Любая часть шаблона может быть заключена в кавычки, чтобы принудительно сопоставить ее как строку.
Поэтому части регулярного выражения не следует заключать в кавычки, если только не установлена regex
опция оболочки :compat31
shopt
...compat31
Если установлено, bash меняет свое поведение на поведение версии 3.1 в отношении аргументов в кавычках оператора
[[
условной команды.=~
Для данного примера попробуйте:
if [[ ! "$dimension" =~ ^[0123456789]+x[0123456789]+$ ]]; then
printf '%s %s\n' "'$dimension'" 'is not a valid dimension.'
fi
regex
должен быть привязан к^...$
, в противном случаеfoo1x1fubar
будет считаться допустимым измерением.
Также помните, что не следует использовать диапазоны 0-9
для проверки входных данных, особенно если это необходимо для очистки в контекстах, чувствительных к безопасности, поскольку во многих локалях эти диапазоны включают в себя гораздо больше символов (или, возможно, объединяющих элементов, состоящих из нескольких символов), чем это было исторически (и по-прежнему происходит в локалях C/POSIX).
Для =~
, bash
's globasciiranges
здесь не поможет. В Ubuntu 19.10 и в en_GB.UTF-8
локали я обнаружил, что bash
' [0-9]
соответствует 1040 различным символам в дополнение к 0123456789, с или без globasciiranges
. По крайней мере, в моем случае они все имели некоторую связь с десятичными цифрами от 0 до 8, но это даже не гарантируется в целом.
С другой стороны, [[:digit:]]
и [0123456789]
соответствует только этим 10 и должен соответствовать любой POSIX-совместимой системе.
Вы также можете сделать это, используя стандартный sh
синтаксис и шаблоны подстановочных знаков, например:
valid_geometry() case $1 in
(*[!x0123456789]* | *x | x* | *x*x*) false;;
(*x*) true;;
(*) false;;
esac
if ! valid_geometry "$dimension"; then
...
fi
Или с помощью ksh globs (также поддерживаемых bash -O extglob
и bash
даже [[
без extglob
) с помощью:
if [[ $dimension != +([0123456789])x+([0123456789]) ]]; then
...
fi
решение2
Хорошо, это, кажется, работает:
if [[ ! "$dimension" =~ [0-9]+x[0-9]+ ]]; then
echo 'wtf meng, the dimension needs an "x" in it.'
exit 1;
fi
но мне интересно, почему заключение в одинарные кавычки не работает:
if [[ ! "$dimension" =~ '[0-9]+x[0-9]+' ]]; then
echo 'wtf meng, the dimension needs an "x" in it.'
exit 1;
fi
вот мое решение:
dimension="3x5"
regex='[0-9]+x[0-9]+'
if [[ ! "$dimension" =~ $regex ]]; then
echo 'wtf meng, the dimension needs an "x" in it.'
exit 1;
fi
Теперь вы можете использовать одинарные кавычки для цитирования регулярного выражения, но вы должны избегать двойных кавычек при ссылке на $regex из [[ ]]. Однако мне все еще интересно, есть ли сокращение для [0-9]+
..