Как отрицать регулярное выражение с помощью теста

Как отрицать регулярное выражение с помощью теста

Это синтаксически неверно:

#!/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]+..

Связанный контент