Linux bash if numbers

Checking if an input number is an integer

I’m trying to check if an input is an integer and I’ve gone over it a hundred times but don’t see the error in this. Alas it does not work, it triggers the if statement for all inputs (numbers/letters)

read scale if ! [[ "$scale" =~ "^3+$" ]] then echo "Sorry integers only" fi 

I’ve played around with the quotes but either missed it or it did nothing. What do I do wrong? Is there an easier way to test if an input is just an INTEGER?

11 Answers 11

if ! [[ "$scale" =~ ^6+$ ]] then echo "Sorry integers only" fi 

if [[ $scale =~ [^0-9] ]] is less convoluted. Doing so, puts the negation in the regular expression instead of the test condition. See below.

Use -eq operator of test command:

read scale if ! [ "$scale" -eq "$scale" ] 2> /dev/null then echo "Sorry integers only" fi 

It not only works in bash but also any POSIX shell. From POSIX test documentation:

n1 -eq n2 True if the integers n1 and n2 are algebraically equal; otherwise, false. 

@lonewarrior556: It works only for integer, see: pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html. I guess you said for any number because you use new test [[ instead of old test [ as mine.

As the OP seems to want only positive integers:

$ is_positive_int()< [ "$1" -ge 0 ] 2>/dev/null && echo YES || echo no; > $ is_positive_int word no $ is_positive_int 2.1 no $ is_positive_int -3 no $ is_positive_int 42 YES 

Note that a single [ test is required:

$ [[ "word" -eq 0 ]] && echo word equals zero || echo nope word equals zero $ [ "word" -eq 0 ] && echo word equals zero || echo nope -bash: [: word: integer expression expected nope 

This is because dereferencing occurs with [[ :

$ word=other $ other=3 $ [[ $word -eq 3 ]] && echo word equals other equals 3 word equals other equals 3 

Note that in bash, it would return yes for » 123 » for instance. You wouldn’t want to use that approach in ksh where it would not only work but also be a command injection vulnerability.

A POSIX and portable solution is:

read scale if [ -z "$" ]; then echo "Sorry integers only" fi 

By far the best answer yet too many people don’t use parameter expansion. This works on arrays too, incl $@: params=(«$») — Keep all positional arguments, but only use numbers — anything else will be converted to null string which conveniently evaluates to 0 in arithmetic evaluations (my use case — function parameter is a list of integers, unset or null should default to 0 but caller sets variable name when unset).

For unsigned integers I use:

read -r scale [ -z "$" ] && [ -n "$scale" ] || echo "Sorry integers only" 
$ ./test.sh 7 $ ./test.sh 777 $ ./test.sh a Sorry integers only $ ./test.sh "" Sorry integers only $ ./test.sh Sorry integers only 

I like that one as it is made with builtins, fast, and seems quite posix. I tried on an old shell (bash 2.0.5) and it works perfectly.

Читайте также:  Linux ubuntu среда разработки

That does the check and outputs your error.

By far the best answer yet too many people don’t use parameter expansion. This works on arrays too, incl $@ : params=(«$») — Keep all positional arguments, but only use numbers — anything else will be converted to null string which conveniently evaluates to 0 in arithmetic evaluations (my use case — function parameter is a list of integers, unset or null should default to 0 but caller sets variable name when unset).

case $1 in ("" | *[!0123456789]*) echo >&2 Sorry, decimal integer only exit 1 esac 

Do not use 1 which often matches a lot more than [0123456789] (especially with bash globs, YMMV for bash’s [[ =~ ]] operator which uses the system regexps where 2 may or may not match more than 0123456789 depending on the system and locale).

Note that you may also want to reject numbers like 08 or 09 which some tools (including bash arithmetic operators) reject as invalid octal numbers.

«Do not use 8 which often matches a lot more» — in which shell? Why? Where did you see this behavior in the wild?

@josch, have you followed the «more on that. » link? I’ve covered that on many Q&As and comments here and elsewhere. See also lists.gnu.org/archive/html/bug-bash/2021-02/msg00054.html for bash

Thank you, that was a very educative read! I’ve adjusted my answer accordingly and will go through my own shell scripts fixing these instances.

In bash, you can use the extended patterns inside [[. ]] :

scale=4 [[ $scale == +([[:digit:]]) ]] || echo "Sorry integers only" # ==> no output 
scale=4.0 [[ $scale == +([[:digit:]]) ]] || echo "Sorry integers only" # ==> Sorry integers only 

For X greater than 0 I use

[ 0$X -gt 0 2>/dev/null ] && echo "is number" || echo "is string" 

this gives no error if X is empty

That’s not only wrong, but also a command injection vulnerability in bash and a few other shells. Try for instance with X=’x -o -v xx[$(reboot)1] -o 1′ in bash (gives true and reboots).

Less convoluted

The negation is now in the regular expression instead of the test condition.

if [[ $scale =~ [^0-9] ]] then echo "Sorry integers only" fi 
  • =~ binary operator where the string to the right of the operator is considered an extended regular expression and matched accordingly (as in regex(3))
  • [^0-9] matches a single character not present in the list 0-9.

That fails to filter out empty values or values that contain non-characters. On some systems and locales 2 matches more than the 0123456789 characters.

The following is POSIX compliant, so it will work in other shells than bash as well. Just checking -z «$» as suggested by another answer here does not take into account that strings starting with zero (except for zero itself) or empty strings are also not valid base-10 integers.

case "$scale" in *[!0123456789]*|0?*|"") echo "Sorry integers only";; esac 

We need to spell out all valid digits because using a range like 0-9 matches on any character (or possibly multi-character collation element) that sorts in between 0 and 9. Thanks to @stéphane-chazelas for this insight. More about that here: https://lists.gnu.org/archive/html/bug-bash/2021-02/msg00054.html

Читайте также:  Linux columns in top

If negative integers are valid in your use case, you can use:

case "$scale" in *[!0123456789-]*|-|?*-*|0?*|-0|"") echo "Sorry integers only";; esac 

Источник

Checking if a Variable Is a Number in Bash

announcement - icon

The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.

To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.

Connect your cluster and start monitoring your K8s costs right away:

1. Overview

Python, Perl, Tcl, and all UNIX shell scripting languages (like Bash) are examples of interpreted languages. This is the reason why Bash reads and interprets one command at a time and doesn’t segregate its variables by type. In fact, Bash is untyped.

In this tutorial, let’s go deeper and see how it’s possible to check if a variable is effectively a number. First, we’re going to show many possible solutions in detail. Second, we’ll explain the idea behind each solution.

2. Comparing Variables

Bash considers its variables as character strings, but it allows all arithmetical operations and comparisons on the variables. The basic idea is that to evaluate if a variable is a number, we need to verify that its value contains only digits.

2.1. Using Regular Expressions

As a first example, let’s write a script called integers.sh that uses a regular expression to make sure the given input is an integer value:

  • $1 contains the value of the parameter passed to the script invocation
  • a regular expression is here defined after the grep command

More precisely, the Unix pipe provides the standard output of the first process (echo command) to the standard input of the second command (grep command). The accepted characters are numbers between 0 and 9. In addition to that, the sign along with the dashes states that we can use negative numbers.

If we want to define the regular expression for the positive numbers, we simply need to remove the dash sign only. So, let’s show two examples of the invocation of the previous script. Using an integer value, we have:

Otherwise, with a string, we get:

As we can see, the regular expression correctly accepts the integer value, and as expected, it rejects the word and doesn’t print it on the console.

2.2. Using the Equal Tilde Operator

Another way to solve the problem is using the Equal Tilde (=~) operator. This allows the use of the regular expressions in an if statement:

#!/bin/bash if ! [[ $1 =~ '^5+$' ]]; then echo "error: Not a number" >&2; exit 1 fi

The right side of the boolean condition is an extended regular expression. If the left side matches, the operator returns 0, and otherwise, it returns 1.

Читайте также:  Nvidia driver linux install run

Let’s group these last instructions in a script called ext-regexp.sh and invoke it:

$ ./ext-regexp.sh a error: Not a number

This means that the script correctly ends with status 0 in case we use a number. Otherwise, it reports the error and exits with status 1.

2.3. Matching Real Numbers

We can simply change the matching rule for the regular expression to recognize the real numbers:

For the real numbers with the sign, we need to use:

3. Conclusions

In this tutorial, we’ve explained how to check if a variable is a number in Bash. The proposed solutions all rely on the use of regular expressions.

Источник

How to test if a variable is equal to a number in shell

When I change Server_Name to 2 , I want it to say: Server Name is 2 . I know it is the if [ $Server_Name=1 ]; part. How do i fix it?

As David points out below, you must use «-eq» to test numeric values. You might also want to check for a blank variable to avoid errors; if [ ! «x$var» = «x» ]; then\n if [ $var -eq 1 ]; then .

5 Answers 5

Your script indicates you are using string comparisons.

Assume server name could be a string instead of number only.

For String comparisons:
if [[ «$Server_Name» == 1 ]]; then

  • Spacing around == is a must
  • Spacing around = is a must
    if [ $Server_Name=1 ]; then is WRONG
  • [[ . ]] reduces errors as no pathname expansion or word splitting takes place between [[ and ]]
  • Prefer quoting strings that are «words»

For Integer comparisons:
if [[ «$Server_Name» -eq 1 ]]; then

I agree with @gilad905. Please use if [ «$Server_Name» = «1» ] or even if [ «$Server_Name» -eq «1» ] for comparing numeric value (would still work if Server_Name is defined with =01 ).

if [ $Server_Name -eq 1 ];then 

Maybe write with quotes «$Server_Name» to be safe from any corner cases where the variable would contain spaces or other wild data.

does not work as intended because the syntax inside the single brackets isn’t special to Bash. As usual, the variable $Server_Name gets substituted by 1, so all the test ( [ ) command sees is a single argument: the string 1=1 . Since that sting has a non-zero length, test returns true.

For POSIX-compliant shells, you can use the following test commands:

checks is the $Server_Name is equal to the string 1 .

checks is the $Server_Name is equal to the number 1 , i.e., it does a numeric comparison instead of a string comparison.

The return value of the two command will differ, e.g., if you define Server_Name=01 . The first one will return false, the second will return true.

Note that if the possibility exists that the variable $Server_Name is undefined, it must be quoted or test will display an error when invoked.

Источник

Оцените статью
Adblock
detector