Тест, является ли строка допустимым целым числом

Я пытаюсь сделать что-то достаточно общее: ввод данных пользователем Синтаксического анализа в сценарии оболочки. Если пользователь обеспечил допустимое целое число, сценарий делает одну вещь, и если не допустимый, это делает что-то еще. Проблема, я не нашел легкое (и довольно изящный) способом сделать это - я не хочу должным быть выбирать его независимо символ символом.

Я знаю, что это должно быть легко, но я не знаю как. Я мог сделать это на дюжине языков, но не Bash!

В моем исследовании я нашел это:

Регулярное выражение, чтобы протестировать, состоит ли строка из допустимого вещественного числа в основе 10

И существует ответ там, который говорит о regex, но насколько я знаю, это - функция, доступная в C (среди других). Однако, это имело то, что было похоже на большой ответ, таким образом, я попробовал его grep, но grep не знал, что сделать с ним. Я попробовал-P, который на моем поле означает рассматривать его как Perl regexp - nada. Тире E (-E) не работал также. И ни один не сделал-F.

Только, чтобы быть ясным, я пробую что-то вроде этого, ища любой вывод - оттуда, я изрублю сценарий для использования в своих интересах независимо от того, что я добираюсь. (IOW, я ожидал, что несоответствующий вход ничего не возвращает, в то время как допустимая строка повторяется.)

snafu=$(echo "$2" | grep -E "/^[-+]?(?:\.[0-9]+|(?:0|[1-9][0-9]*)(?:\.[0-9]*)?)$/")
if [ -z "$snafu" ] ;
then
   echo "Not an integer - nothing back from the grep"
else
   echo "Integer."
fi

Кто-то проиллюстрировал бы, как это наиболее легко сделано?

Откровенно говоря, это - недостаток ТЕСТА, по-моему. Это должно иметь флаг как это

if [ -I "string" ] ;
then
   echo "String is a valid integer."
else
   echo "String is not a valid integer."
fi

108
задан codeforester 25 May 2018 в 05:43
поделиться

5 ответов

[[ $var =~ ^-?[0-9]+$ ]]
  • ^ указывает начало входного шаблона
  • - является буквальным "-"
  • ? означает «0 или 1 из предшествующих ( -
  • + означает «1 или более из предыдущих ( [0-9] ) "
  • $ указывает конец входного шаблона

Таким образом, регулярное выражение соответствует необязательному - (для случая отрицательных чисел), за которым следует одна или несколько десятичных цифр.

Ссылки :

171
ответ дан 24 November 2019 в 03:28
поделиться

Можно взглянуть на реализацию Model-View-View Model в WPF .

Это не рамка, как .NET MVC, но в ее основе MVC является образцом, а MVVM является близким аналогом для WPF.

-121--4407445-

Поэтому был создан const _ cast . Просто помните, чтобы не стрелять ногой.

Изменить: ОК, я признаю - const_cast не был сделан для этой проблемы вообще. Это может сработать с вашим компилятором, но вы не можете рассчитывать на это, и если демоны вылетят из ваших ноздрей, пожалуйста, не вините меня.

-121--3842614-

Для обеспечения переносимости до-Bash 3,1 (когда был введен тест = ~ ) используйте expr .

if expr "$string" : '-\?[0-9]\+$' >/dev/null
then
  echo "String is a valid integer."
else
  echo "String is not a valid integer."
fi

expr STRING: REGEX выполняет поиск REGEX, привязанного в начале ПОСЛЕДОВАТЕЛЬНОСТЬ, повторяя первую группу (или длину совпадения, если нет) и возвращая успех/сбой. Это старый синтаксис regex, следовательно, избыток \. -\? означает «может быть - », [0-9 ]\+ означает «одну или несколько цифр», а $ означает «конец последовательности».

Bash также поддерживает расширенные глобусы, хотя я не помню, с какой версии.

shopt -s extglob
case "$string" of
    @(-|)[0-9]*([0-9]))
        echo "String is a valid integer." ;;
    *)
        echo "String is not a valid integer." ;;
esac

# equivalently, [[ $string = @(-|)[0-9]*([0-9])) ]]

@ (- |) означает « - или ничего», [0-9] означает «цифра», а * ([0-9]) означает «ноль или больше цифр».

9
ответ дан 24 November 2019 в 03:28
поделиться

Вы можете удалить нецифровые данные и провести сравнение. Вот демо-скрипт:

for num in "44" "-44" "44-" "4-4" "a4" "4a" ".4" "4.4" "-4.4" "09"
do
    match=${num//[^[:digit:]]}    # strip non-digits
    match=${match#0*}             # strip leading zeros
    echo -en "$num\t$match\t"
    case $num in
        $match|-$match)    echo "Integer";;
                     *)    echo "Not integer";;
    esac
done

Вот как выглядит результат теста:

44      44      Integer
-44     44      Integer
44-     44      Not integer
4-4     44      Not integer
a4      4       Not integer
4a      4       Not integer
.4      4       Not integer
4.4     44      Not integer
-4.4    44      Not integer
09      9       Not integer
2
ответ дан 24 November 2019 в 03:28
поделиться

Вот еще один вариант (только с использованием встроенной команды test и ее кода возврата):

function is_int() { return $(test "$@" -eq "$@" > /dev/null 2>&1); } 

input="-123"

if $(is_int "${input}");
then
   echo "Input: ${input}"
   echo "Integer: $[${input}]"
else
   echo "Not an integer: ${input}"
fi
3
ответ дан 24 November 2019 в 03:28
поделиться

Мне нравится решение, использующее тест -eq , потому что оно в основном однострочное.

Мое собственное решение заключалось в том, чтобы использовать расширение параметра, чтобы отбросить все числа и посмотреть, осталось ли что-нибудь. (Я все еще использую 3.0, раньше не использовал [[ или expr , но рад их видеть.)

if [ "${INPUT_STRING//[0-9]}" = "" ]; then
  # yes, natural number
else
  # no, has non-numeral chars
fi
9
ответ дан 24 November 2019 в 03:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: