Bash invalid arithmetic operator error token is

cat test.sh #!/bin/bash key="index"; arr[$key]="val" echo ${arr[${key}]} /bin/bash-x test.sh + key=index + arr[$key]=val + echo val val then I modify the test.sh: #!/bin/bash key="index.index"...

This:

key="index";
arr[$key]="val"
echo ${arr[${key}]}

only appears to work. Since arr is an ordinary array, not an associative array, it can only be indexed by non-negative integer values.

Consider this valid code:

index=42
key="index"
arr[$key]="val"
echo ${arr[42]}
echo ${arr[index]}
echo ${arr[$index]}
echo ${arr['index']}
echo ${arr["index"]}
echo ${arr[index]}

All the echo statements print val. Since the index is treated as an arithmetic expression, it can refer to a variable (in this case, $index) either with or without the $ prefix — even if it’s a quoted string.

In your code, where you never assigned a value to $index, ${arr[${key}]} expands to ${arr[index]}, which is equivalent to ${arr[$index]}, which is treated (by default) as equivalent to ${arr[0]}.

(If you have set -o nounset, then references to unset variables are treated as errors, and your code will produce an error message.)

Your second chunk of code:

key="index.index";
arr[$key]="val"
echo ${arr[${key}]}

is invalid because index.index is not a valid variable name — even though you probably meant it to be just a string used as an array index.

If you want arr to permit arbitrary strings as indices, it needs to be an associative array. You can create a non-associative array simply by assigning to it (or by using declare -a), but an associative array can only be created with declare -A.

Associative arrays were added to bash in version 4. If you’re using an earlier version of bash, declare -A is not supported. You’ll need to upgrade to a newer bash, code up some clumsy alternative, or use a language that does support associative arrays, like Awk, Python, or Perl.

Adding declare -A arr (as user000001’s answer suggests) should solve the problem (if you have bash 4), but it’s instructive to understand what your original code is actually doing (or rather not doing).

(BTW, thanks for asking this; I learned a lot as I was composing this answer.)

Содержание

  1. «invalid arithmetic operator» in shell
  2. 3 Answers 3
  3. bash — syntax error invalid arithmetic operator error token is
  4. bash syntax error: invalid arithmetic operator with token «@mail.com»
  5. 2 Answers 2
  6. getting syntax error: invalid arithmetic operator (error token is «. «) #357
  7. Comments
  8. invalid arithmetic operator (error token is » «) with for loop
  9. 3 Answers 3
  10. Linked
  11. Related
  12. Hot Network Questions
  13. Subscribe to RSS

«invalid arithmetic operator» in shell

then I modify the test.sh:

/bin/bash -x test.sh

why this error appears, any suggestion will be appreciate!

3 Answers 3

only appears to work. Since arr is an ordinary array, not an associative array, it can only be indexed by non-negative integer values.

Consider this valid code:

All the echo statements print val . Since the index is treated as an arithmetic expression, it can refer to a variable (in this case, $index ) either with or without the $ prefix — even if it’s a quoted string.

In your code, where you never assigned a value to $index , $]> expands to $ , which is equivalent to $ , which is treated (by default) as equivalent to $ .

(If you have set -o nounset , then references to unset variables are treated as errors, and your code will produce an error message.)

Your second chunk of code:

is invalid because index.index is not a valid variable name — even though you probably meant it to be just a string used as an array index.

If you want arr to permit arbitrary strings as indices, it needs to be an associative array. You can create a non-associative array simply by assigning to it (or by using declare -a ), but an associative array can only be created with declare -A .

Associative arrays were added to bash in version 4. If you’re using an earlier version of bash, declare -A is not supported. You’ll need to upgrade to a newer bash, code up some clumsy alternative, or use a language that does support associative arrays, like Awk, Python, or Perl.

Adding declare -A arr (as user000001’s answer suggests) should solve the problem (if you have bash 4), but it’s instructive to understand what your original code is actually doing (or rather not doing).

(BTW, thanks for asking this; I learned a lot as I was composing this answer.)

Источник

bash — syntax error invalid arithmetic operator error token is

Приветствую! Ребята подскажите где я не догоняю?

Нужно выполнить проверку значений с первого массива во втором.

Элементы массива закавычь

Пробовал и ‘ кавычить и » кавычить. Одно и тоже.

Это из-за противоестественного интеллекта такое, если цифры — значить индекс, а не ассоциация. Добавьте везде букву при заполнении и сравнениях.

Жесть, а нет может ключа какого? что бы указал что здесь строка арифметика не нужна.

Добавил слово ip /usr/net/net-up: line 67: ip172.20.0.3/24: syntax error: invalid arithmetic operator (error token is «.20.0.3/24»)

Нате. Специально добавил несуществующий в конец current_ifip

На bash’e любой !Ъ сможет, даешь POSIX shell!

state_ip это не ассоциативный массив вообще-то, не смущает?

У вас тоже не bourne 🙂 Все эти $(cmd) $

. Если уж юзаете set —, то накой вообще этот load()? Делайте IFS=» » set —. Ну и т д.

А это башизм, да 🙂

Если уж юзаете set —, то накой вообще этот load()?

Чисто эстетически смотрится лучше, ИМХО. Сам смысл load() что бы построить подобие хеш-таблицы.

Этого не понял. Зачем IFS менять в данном случае ? .

Да это чисто новомодный эфемизм к обратным апострофам, мож и POSIX, но не такой уж и древний.

Для гарантии. Это правильный стиль, ибо меняет не глобально и самодокументированно для демонстрации чего хотят сделать в этой строчке.

Это правильный стиль, ибо меняет не глобально и самодокументированно для демонстрации чего хотят сделать в этой строчке.

Я понимаю, что он делает, и для чего нужен в целом. Я спрашивал за другое — чем или как именно замена IFS поможет конкретно в этом случае ? .

чем или как именно замена IFS поможет конкретно в этом случае

Сделает ровно то что вы делаете load() — распарсит строку по аргументам с разделителем пробел.

Почти то что нужно, но не совсем. Помогите доработать.

Первый раз ip добавляются второй раз прогоняю скрипт он снова пытается добавить. Т.е. не отрабатывает проверка в списке.

Источник

bash syntax error: invalid arithmetic operator with token «@mail.com»

I have a script that performs a SQL SELECT and sends some e-mails using the output but there is an issue with the script causing the error message:

line 34: johne@mail.com: syntax error: invalid arithmetic operator (error token is «@mail.com»)

Here is the script:

2 Answers 2

The problem is that you are trying to perform a string comparison inside an arithmetic expression. Either switch to a compound expression:

or check that you are accessing the correct element of msgData .

It first seemed to me that this is a limitation of the implementation of associative arrays in bash (as of v4.3.11 here).

Associative arrays are created using

Arrays are assigned to using compound assignments of the form

where each value is of the form [subscript]= string.

And then you look up subscript a few lines earlier:

The subscript is treated as an arithmetic expression that must evaluate to a number.

So it’s saying a string «foo@bar» can’t evaluate to a number, and can’t be used as an array key? But that doesn’t explain why strings without «@» can.

The confusing part is also that when you do the assignment manually, e.g.

That works fine. Bother.

The solution for this, as it turns out, is to repeat the declare -A part in the assignment, like this:

In the specific example above, it’s probable that $ gets evaluated in integer context because you use the comparison.

So I’d wager that you want to do something like quote it to escape that context first.

Or simply do it with fewer shorthands, without the :- modifier, which really contributes to the impression of line noise when combined with all the other punctuation on that line. For example:

Источник

getting syntax error: invalid arithmetic operator (error token is «. «) #357

This might not be a bash-completion issue, but I hope at least by explaining the issue that I could get some help debugging the issue.

The issue is this:

$ a.b bash: a.b: syntax error: invalid arithmetic operator (error token is «.b»)

If I source bash_completion like so:

everything works like expected:

In my .bashrc I have the following

I have also tried explicitly sourcing /usr/local/Cellar/bash-completion@2/2.8/share/bash-completion/bash_completion in my bashrc, but seems to have no effect. For some reason it only works when I do it in my shell.

The text was updated successfully, but these errors were encountered:

See «Troubleshooting» in README.md.

I’ve tried sourcing bash_completion also in my .bash_profile, also my .bash_profile only sources .bashrc so this should be ok.
I’ve tried to run the same commands with set +v and set +x , but not getting any more useful output.

Or was there any other sections in the Troubleshooting guide you would recommend?

To get a trace what’s happening when you hit tab, you should be running under e.g. set -x , not set +x (which turns it off).

Thanks. When running $ a.b [tab] now yields:

Ah, right, that’s fixed in commit a47bd37 which is included in 2.9.

. or probably not after all, actually. Anyway I’ll try to have a closer look soon.

I believe the error occurs when we try to access the _xspecs associative array to check if there’s a completion for a.b there. I can simulate the error for a non-associative array:

. but _xspecs is defined as an associative array, and I cannot reproduce with such one:

It’s like that in 2.8 too, so I have no more ideas at the moment.

I see. Like mentioned, this works when I explicitly source bash_completion again in my shell, even though I do it in my .bashrc as well — which sounds wierd. Any way to verify that the sourcing operation done in .bashrc was successful?

bash —norc gives you a «clean» shell, you can do set -x there and invoke the same commands your shell does when it starts up. I’d first triple check that what you manually source in your shell is the same bash_completion your rcfiles do.

The issue was resolved when I moved the sourcing of bash-completion out of a function inside my .bashrc . (https://unix.stackexchange.com/questions/151889/why-does-bashs-source-command-behave-differently-when-called-from-a-function)
Thank very much for help with debugging this. (edit: don’t think that issue had the same problem)

Not sure if this is something that could be detected and prevented, I’ll leave it up to you to decide.

Источник

invalid arithmetic operator (error token is » «) with for loop

gives error solution.sh: line 2: ((: c

I am using BASH. What is wrong with the for loop?

edit: I am working on the BASH hackerrank IDE and although this code is not directly related to the problem in this link, I am getting this error.

3 Answers 3

I’ve reproduced this error message by pressing Ctrl-E after 1. It looked like this:

So make sure you are not pressing some strange combination of keys before enter.

You need to add this line

at the top of solution.sh .

(if your bash is at a different location, do, in a terminal,

to determine its location)

@picasso13 just a wild guess cause it got me(and yield the same mysterious error when I tried to loop with array constructed from the input). There are 2 inputs on hackerRank(the first one is actually the size of the second). It solved my problem when I threw away the first and make sure my iteration was working on the list of numbers:

if you comment out my read ignore you’ll reproduce the issue.

Linked

Hot Network Questions

To subscribe to this RSS feed, copy and paste this URL into your RSS reader.

Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.1.14.43159

By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.

Источник

Last updated: 2022-07-16

Math and Arithmetic are often used in Bash scripting, especially when writing crontab reports, monitoring plugins, setting up scripts with dynamic configurations, or other automation tasks like showing a Raspberry PI CPU temperature. There is always some arithmetic calculation to be made.

This post covers how to do basic mathematical operations (elementary arithmetic like multiplication and addition) in Bash with integers or floating-point numbers.

TL;DR: x=3; y=$((x+2)); echo $y will print 5

Introduction to Integers and Floating-Points

Before we get into the details on how to do Math in Bash, remember that an integer is a whole number that is not a fraction or decimal and is anywhere from zero to positive or negative infinity. For example, 42, 36, and -12 are integers, while 3.14 and √2 are not. The set of integers includes all negative integers (whole numbers that has value less than zero), zero, and all positive integers (whole numbers that has value larger than zero). An integer and its opposite are the same distance from zero.

A floating-point number is a computing programming term to represent a real number with a fractional part. For example 3.14, √2, -10.5, 4e-2 are floating points numbers. A floating-point is specified by a base (binary or decimal), a precision, and an exponent range. It is usually in binary made of 32 (simple precision) or 64 bits (double precision), thought the
IEEE 754 standard mention more formats.

Format Total bits Significand bits Exponent bits Smallest number Largest number
Single precision 32 23 + 1 sign 8 ≈ 1.2 ⋅ 10-38 ≈ 3.4 ⋅ 1038
Double precision 64 52 + 1 sign 11 ≈ 2.2 ⋅ 10-308 ≈ 1.8 ⋅ 10308

You may see a floating-point being represented in the form of significand x base exponent. For example: 3.14 = 314 x 10-2

What are the Bash Arithmetic Operators?

The Bash shell has a large list of supported arithmetic operators to do math calculations. They work with the let, declare, and arithmetic expansion methods described further below in this post.

Arithmetic Operator Description
id++, id– variable post-increment, post-decrement
++id, –id variable pre-increment, pre-decrement
-, + unary minus, plus
!, ~ logical and bitwise negation
** exponentiation
*, /, % multiplication, division, remainder (modulo)
+, — addition, subtraction
«, » left and right bitwise shifts
<=, >=, <, > comparison
==, != equality, inequality
& bitwise AND
^ bitwise XOR
| bitwise OR
&& logical AND
|| logical OR
expression ? expression : expression conditional operator
=, *=, /=, %=, +=, -=, «=, »=, &=, ^=, |= assignment

Doing Math in Bash with Integer

Natively, Bash can only do integer arithmetic, if you need to do arithmetic operations that requires floating-point arithmetic, see the next section.

Using the expr command line

The legacy way to do math calculations with integer, and only integer, has been for a long time to use the expr command line. Though, this method can be slow as expr is a binary, not a shell builtin. It will fork a new process which is not ideal in a large for-loop. Also, the expr behavior may vary between systems depending on the implementation.

# Subtraction
[me@linux ~]$ expr 1 - 1
0
# Addition
[me@linux ~]$ expr 1 + 1
2
# Assign result to a variable
[me@linux ~]$ myvar=$(expr 1 + 1)
[me@linux ~]$ echo $myvar
2
# Addition with a variable
[me@linux ~]$ expr $myvar + 1
3
# Division
[me@linux ~]$ expr $myvar / 3
0
# Multiplication
[me@linux ~]$ expr $myvar * 3
6

⚠️ When doing a multiply by make sure to escape the asterisk (*), or any other bash wildcards, to prevent pattern expansion in Bash. You can escape a special character using the backslash (), example: expr $myvar * 3. Not escaping the * would lead to an expr: syntax error.

Using the let or declare shell builtin commands

An alternative to the legacy expr command, is to use the Bash builtin command let or declare to evaluate Arithmetic Expressions. The declare builtin method require the -i option to do an Integer Declaration.

[me@linux ~]$ myvar=6 ; echo $myvar
6
[me@linux ~]$ let myvar+=1 ; echo $myvar
7
[me@linux ~]$ let myvar+1 ; echo $myvar
8
[me@linux ~]$ let myvar2=myvar+1 ; echo $myvar2
9

With both methods, you can combine multiple expressions on a single line as let and declare evaluate each argument as a separate arithmetic expression.

[me@linux ~]$ let x=4 y=5 z=x*y u=z/2
[me@linux ~]$ echo $x $y $z $u
4 5 20 10

[me@linux ~]$ declare -i x=4 y=5 z=x*y u=z/2
[me@linux ~]$ echo $x $y $z $u
4 5 20 10

⚠️ Integer Declaration using the declare -i notation can lead to confusing or hard-to-read shell scripts. A variable set as an integer may accept non-integer values, but it won’t store and output the expected new string and may error out. Using declare -i force a variable to be an arithmetic context only. It is like prefixing the variable assignment with the let command every time. Instead, it is generally clearer to use the Bash Arithmetic Expansion as detailed in the next section.

[me@linux ~]$ declare -i myvar3=myvar2*2 ; echo $myvar3
18
[me@linux ~]$ echo $myvar3 ; myvar3="none"; echo $myvar3
18
0

Using the Bash Arithmetic Expansion

The recommended way to evaluate arithmetic expressions with integers in Bash is to use the Arithmetic Expansion capability of the shell. The builtin shell expansion allows you to use the parentheses ((...)) to do math calculations.

The format for the Bash arithmetic expansion is $(( arithmetic expression )). The shell expansion will return the result of the latest expression given.

The $((...)) notation is what is called the Arithmetic Expansion while the ((...)) notation is called a compound command used to evaluate an arithmetic expression in Bash.

The Arithmetic Expansion notation should be the preferred way unless doing an arithmetic evaluation in a
Bash if statement, in a
Bash for loop, or similar statements.

👉 The square brackets $[...] can also do Arithmetic Expansion in Bash, though this notation has been deprecated and should be avoided. Instead, prefer the use of $((...)) instead.

[me@linux ~]$ myvar=3 && echo $myvar
3
[me@linux ~]$ echo $((myvar+2))
5
[me@linux ~]$ myvar=$((myvar+3))
[me@linux ~]$ echo $myvar
6
[me@linux ~]$ ((myvar+=3))
[me@linux ~]$ echo $myvar
9

This allows you to use C-style programming and easily increment or decrement a variable in Bash using the ++ or -- arithmetic operators. All the operators listed in the table above are fully available when using Arithmetic Expansion.

[me@linux ~]$ myvar=3 && echo $myvar
3
[me@linux ~]$ echo $((myvar++))
3
[me@linux ~]$ echo $myvar
4
[me@linux ~]$ echo $((++myvar))
5
[me@linux ~]$ echo $myvar
5

In the previous section, we show an example with let containing multiple expressions on a single line. This is also possible with Arithmetic Expansion. The only difference is that multiple expressions must be separated by a comma (,).

[me@linux ~]$ echo $((x=4,y=5,z=x*y,u=z/2))
10
[me@linux ~]$ echo $x $y $z $u
4 5 20 10

[me@linux ~]$ ((x=4,y=5,z=x*y,u=z/2)) ; echo $x $y $z $u
4 5 20 10

Doing Floating-point Arithmetic in Bash

Using the printf builtin command

A noteworthy but unconventional way to do floating-point arithmetic in native bash is to combine Arithmetic Expansion with printf using the scientific notation. Since you can’t do floating-point in bash, you would just apply a given multiplier by a power of 10 to your math operation inside an Arithmetic Expansion, then use printf to display the float.

For example, the operation 2/3 in Artithmetic Expansion as $((2/3)) would return 0. To get the floating number using printf you would use a formula like below where <precision> would be the floating-point precision to display and <multiplier> the power of ten multipliers. Similarly, a multiplier of 3 would mean 10**3, which is 1000.

printf %.<precision>f "$((10**<multiplier> * 2/3))e-<multiplier>

Note that the floating point precision in %.<precision>f shouldn’t be higher than the multiplier itself as it will just fill with zeros.

[me@linux ~]$ printf %.3f "$((10**3 * 2/3))e-3"
0.666
[me@linux ~]$ printf %.1f "$((10**3 * 2/3))e-3"
0.7
[me@linux ~]$ printf %.5f "$((10**3 * 2/3))e-3"
0.66600

Using the awk command line

Another way to do floating-point arithmetic is to use GNU awk. You can use all the arithmetic operators listed in the table earlier in this post and the printf function to adjust the precision of the printed results.

[me@linux ~]$ awk "BEGIN {print 100/3}"
33.3333
[me@linux ~]$ awk "BEGIN {x=100/3; y=6; z=x*y; print z}"
200
[me@linux ~]$ awk "BEGIN {printf "%.2fn", 100/3}"
33.33

When using negative values, make sure to leave white space between signs.

[me@linux ~]$ awk "BEGIN {print -8.4--8}"
awk: cmd. line:1: BEGIN {print -8.4--8}
awk: cmd. line:1:                    ^ syntax error
[me@linux ~]$ awk "BEGIN {print -8.4 - -8}"
-0.4

Using the bc command line

Since you can’t do floating-point arithmetic natively in Bash, you will have to use a command-line tool. The most common one is “
bc — An arbitrary precision calculator language
”.

To start the interactive mode, you simply need to type bc in your command prompt. You can use the -q (quiet) option to remove the initial bc banner.

[me@linux ~]$ bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
3*5.2+7/8
15.6
15.6+299.33*2.3/7.4
108.6

Of course, you can also use bc in a non-interactive mode by using the STDIN to send your formula to bc then get the output on STDOUT, or by using the
here-doc notation.

# Example of piped arithmetic expression to the bc STDIN
[me@linux ~]$ echo "15.6+299.33*2.3/7.4" | bc
108.6

# Example using the here-doc notation
[me@linux ~]$ bc <<< "15.6+299.33*2.3/7.4" 
108.6

There are four special variables, scale, ibase, obase, and lastscale defines how some operations use digits after the decimal point.  The default value of scale is 0. ibase and obase define the conversion base for input and output numbers.  The default for both input and output is base 10. last (an extension) is a variable that has the value of the last printed number.

The “scale” variable is essential for the precision of your results, especially when using integers only.

👉 Note: you can also use bc -l to use mathlib and see the result at max scale.

[me@linux ~]$ echo "2/3" | bc
0
[me@linux ~]$ echo "scale=2; 2/3" | bc
.66
[me@linux ~]$ echo "(2/3)+(7/8)" | bc
0
[me@linux ~]$ echo "scale=2;(2/3)+(7/8)" | bc
1.53
[me@linux ~]$ echo "scale=4;(2/3)+(7/8)" | bc
1.5416
[me@linux ~]$ echo "scale=6;(2/3)+(7/8)" | bc
1.541666
[me@linux ~]$ echo "(2/3)+(7/8)" | bc -l
1.54166666666666666666

👉 If you want to go further with bc, read my post on
Advanced Math Calculation using bc with an example on how to write a simple arithmetic calculator or to find the factorial of a number.

Detailed Examples & FAQ

How to calculate a percentage in Bash?

You can calculate a floating-point precision percentage in Bash using the printf method and Arithmetic Expansion, or you can calculate a rounded integer percentage using Arithmetic Expansion with the ((...)) notation.

The round-up approach leverages the shell behavior to round toward zero (0). We first calculate twice the percentage then subtract the regular percentage from it. This gives us the formula: roundup = (int) (2 * x) - (int) x where x is the percentage calculation.

[me@linux ~]$ fileProcessed=17; fileTotal=96;

# Floating-point precision using builtin printf method and Arithmetic Expansion
[me@linux ~]$ printf %.2f%% "$((10**3 * 100 * $fileProcessed/$fileTotal))e-3"
17.71%

# Rounding Up Using Arithmetic Expansion and Integers only
[me@linux ~]$ echo $((200 * $fileProcessed/$fileTotal))
35
[me@linux ~]$ echo $((100 * $fileProcessed/$fileTotal ))
17
[me@linux ~]$ echo $((200 * $fileProcessed/$fileTotal -  100 * $fileProcessed/$fileTotal ))%
18%

How to find a factorial in a shell script?

To calculate the factorial of a number in Bash or any POSIX shell, you can use the Arithmetic Expansion and a recursive function. The factorial function symbol in mathematic is ! and a factorial is defined by the formula n! = (n-1)! * n.

[me@linux ~]$ function f() {
  local x=$1
  if ((x<=1)); then
     echo 1
  else
     n=$(f $((x-1)))
     echo $((n*x))
  fi
}
[me@linux ~]$ f 1
1
[me@linux ~]$ f 2
2
[me@linux ~]$ f 3
6
[me@linux ~]$ f 6
720
[me@linux ~]$ f 8
40320

⚠️ This solution is limited to the maximum value of a numeric shell variable in your environment. You can try to resolve the following arithmetic expression echo $((2**64)). If the result is zero, your platform and shell environment won’t support beyond the 20 factorial. Trying to resolve a larger number factorial with this method would lead to inaccurate results. Therefore, you should prefer using bc for reliable results without such constraints. For an example of a recursive factorial function using bc see
How to find factorial of a number in a shell script using bc?.

How to create a simple bash calculator function?

As a thought experiment, you can create a calculator command to do math by using a
bash function, a bash arithmetic expression, and a bash variable inference. Every time the calculator function is called, it will update a variable name by a given value or by default 1 with a given arithmetic operator. Example: counter <var_name> <operator> <value>. You can also implement an interactive version of a
simple calculator by using bc.

[me@linux ~]$ A=0; B=0;
[me@linux ~]$ calculator() ((${1}=${!1}${3:-+}${2:-1}))
[me@linux ~]$ echo "Counter A=$A and B=$B"
Counter A=0 and B=0
[me@linux ~]$ calculator A; calculator B
[me@linux ~]$ echo "Counter A=$A and B=$B"
Counter A=1 and B=1
[me@linux ~]$ calculator A 5; calculator B 2
[me@linux ~]$ echo "Counter A=$A and B=$B"
Counter A=6 and B=3
[me@linux ~]$ calculator A 5 /; calculator B 2 "*"
Counter A=1 and B=6

Obviously, this example is just to demonstrate some of the concepts to do math while using other bash constructs. For a simple variable assignment, you should prefer to use the assignments
bash arithmetic operators.

How to do math on a date using Arithmetic Expansion and printf?

Below is a simple example of doing a date manipulation with a math subtraction in shell script by using the new $EPOCHSECONDS variable from
GNU Bash version 5 and printf date formatting. The example shows the current time minus 86400 seconds.

[me@linux ~]$ echo $EPOCHSECONDS
1589153003
[me@linux ~]$ printf 'Current day of the month is the %(%d)Tn' $EPOCHSECONDS
Current day of the month is the 10
[me@linux ~]$ printf 'Previous day of the month was the %(%d)Tn' $((EPOCHSECONDS-86400))
Previous day of the month was the 09

👉 Read more on how to manipulate and format dates in bash in the post
How To Format Date and Time in Linux, macOS, and Bash?.

How to use different arithmetic bases in an Arithmetic Expansion?

With the Bash Arithmetic Expansion, you can perform calculations between different arithmetic bases. For example, add a base 10 integer to a base 2 integer. To do so, you can prefix each number with the base identifier and the hashtag character #, using the form base#number. The base must be a decimal between 2 and 64 representing the arithmetic base. The default base value used in bash arithmetic expansion is the base 10.

Note that, you can also prefix numbers with a leading zero 0 to represent octal numbers (base 8). A leading 0x or 0X would be interpreted as an hexadecimal. Also, the dollar sign $ is required in front of a variable when specifying a base identifier

[me@linux ~]$ echo $(( 10#2 + 2#1 ))
3
[me@linux ~]$ echo $(( 2 + 2#1 ))
3
[me@linux ~]$ echo $(( 10#2 + 16#aa ))
172
[me@linux ~]$ echo $(( 010 + 16#aa ))
178
[me@linux ~]$ echo $(( 0x10 + 16#aa ))
186
[me@linux ~]$ x=2 ; y=1a ; echo $(( x * 16#$y ))
52

⚠️ Using a base identifier only works with unsigned integers. There is a trick to workaround the issue and move the sign in front of the base identifier, see example below. In general, when doing complex math calculation, you should prefer another solution like using the
Linux bc command line.

[me@linux ~]$ x=-08 ; echo $(( 10#$x ))
bash: -08: value too great for base (error token is "08")
[me@linux ~]$ echo $(( ${x%%[!+-]*}10#${x#[-+]} ));
-8

How to solve the bash error value too great for base (error token is…?

As mentioned above, Bash Arithmetic Expression will automatically consider numbers with leading zero as octal numbers (base 8). When a variable is expended to represent a number with leading zeros and composed with numbers equal or above 8, it will lead to a bash arithmetic error like bash: 08: value too great for base (error token is "08").

[me@linux ~]$ x=01 ; echo $((x+1))
2
[me@linux ~]$ x=0105 ; echo $((x+1))
70
[me@linux ~]$ x=08 ; echo $((x+1))
bash: 08: value too great for base (error token is "08")

To prevent such issues, you must remove the leading zeroes on the variable before doing the Arithmetic Expansion. This can be easily done with the
Bash wildcards and the extended globbing patterns.

Though, a simpler solution may be to ensure the variable is using a base identifier for the base 10 instead of the default representation (see question above). You must use the dollar sign $ in front of a variable when using the base identifier notation.

# Example using extended glob
[me@linux ~]$ shopt -s extglob
[me@linux ~]$ x=08 ; x=${x##+(0)}; echo $((x+1))
9

# Example using a base 10 identifier
[me@linux ~]$ x=08 ; echo $((10#$x+1))
9

If you are getting this error when using signed numbers, then refer to the previous question as the base identifier only works with unsigned numbers.

How to solve the syntax error: invalid arithmetic operator?

When using Arithmetic Expansion, you may encounter the following error:

syntax error: invalid arithmetic operator (error token is ...)

This error is generally due to improperly formatted variables or integers used in the arithmetic expression. The most common mistake would be to try to use a floating-point number, which would fail as such.

[me@linux ~]$ echo "$((20.0+7))"
-bash: 20.0/7: syntax error: invalid arithmetic operator (error token is ".0+7")

Another mistake would be assigning a value to a variable with hidden characters and then using that variable in the arithmetic expansion.

[me@linux ~]$ a=$' 3r'
[me@linux ~]$ echo "$((a+7))"
")syntax error: invalid arithmetic operator (error token is "

You will notice that in such cases, the error message even gets mangled due to the carriage return character r in the variable. To prevent such issues, you will want to ensure the variables you use are properly formatted by stripping out control characters, mainly those with ASCII values from 1 (octal 001) to 31 (octal 037). You can do that by using the
shell parameter expansion.

[me@linux ~]$ echo "$((${a//[ $'01'-$'37']}+7))"
10

👉 Before Bash version 5, you may need to ensure the right collating order of the ASCII values by using shopt -s globasciiranges. Though, since Bash version 5, you don’t need to worry about the globasciiranges option since it is now set by default. Read more about Bash 5 with the post
What’s New in GNU Bash 5?

How to solve the bash error integer expression expected?

When using the test or single square bracket [ commands with a
conditional expression, you may encounter the error integer expression expected. This error will occur when you try to make an arithmetic comparison on strings, i.e., not whole numbers. It is similar to the invalid arithmetic operator error when using the double square brackets [[ as mentioned above. Make sure the variable you use is free of invalid characters; see the previous question on
invalid arithmetic operator.

Note that it is best practice to use the bash arithmetic compound expression with actual arithmetic operators instead of the legacy -lt, -gt, -le, and -ge.

# ERROR
[me@linux ~]$ [ 1 -lt 4.0 ] && echo "1 is smaller than 4.0"
bash: [: 4.0: integer expression expected

# CORRECT
[me@linux ~]$ [ 1 -lt 4 ] && echo "1 is smaller than 4"
1 is smaller than 4

# BEST
[me@linux ~]$ ((1<4)) && echo "1 is smaller than 4"
1 is smaller than 4

System info:

MacOS 10.14.6

~ $ bash --version
GNU bash, version 5.0.11(1)-release (x86_64-apple-darwin18.6.0)

~ $ brew info bash-completion@2
bash-completion@2: stable 2.8 (bottled), HEAD
...

This might not be a bash-completion issue, but I hope at least by explaining the issue that I could get some help debugging the issue.

The issue is this:

$ a.b [tab]

yields

$ a.b bash: a.b: syntax error: invalid arithmetic operator (error token is ".b")

If I source bash_completion like so:

$ source /usr/local/share/bash-completion/bash_completion

everything works like expected:

$ a.b [tab] [tab]

yields

like expected.

In my .bashrc I have the following

  export BASH_COMPLETION_COMPAT_DIR="/usr/local/etc/bash_completion.d"
  [[ -r "/usr/local/etc/profile.d/bash_completion.sh" ]] && . "/usr/local/etc/profile.d/bash_completion.sh"

I have also tried explicitly sourcing /usr/local/Cellar/bash-completion@2/2.8/share/bash-completion/bash_completion in my bashrc, but seems to have no effect. For some reason it only works when I do it in my shell.

Coming from a Python background, this is my first simple Bash script and it does not work. I’m confused.

#!/bin/bash
RTCHOST='192.168.0.143'
PANEL1=$(client read-value --host $RTCHOST --name dc_1)
echo Panel1: $PANEL1
PANEL2=$(client read-value --host $RTCHOST --name dc_2)
echo Panel2: $PANEL2
PANELCONSUMPTION=$(($PANEL1 + $PANEL2))
echo Consumption: $PANELCONSUMPTION

When I run the script, I get a syntax error:

invalid arithmetic operator

What’s wrong?

BeastOfCaerbannog's user avatar

asked Nov 5, 2022 at 10:13

Pythonaire's user avatar

0

I guess $PANEL1 and $PANEL2 are floating point numbers. However, Bash is only capable of handling integers, not floating point numbers, as explained in Arithmetic Expansion. If you try to sum floating point numbers, you will get the invalid arithmetic operator error.

Simply try it here:

#!/bin/bash
A='5'
B='6.4'
C=$(($A + $B))
echo $C

Adding floating point numbers is described in this Stack Overflow thread: How can I add numbers in a Bash script?

In essence, you can use an external utility, such as bc, to do the operation as shown in this example:

#!/bin/bash
A='5'
B='6.4'
C=$(echo $A + $B | bc) 
echo $C

This works and returns the expected value of 11.4.

BeastOfCaerbannog's user avatar

answered Nov 5, 2022 at 11:08

dummyuser's user avatar

dummyuserdummyuser

8831 gold badge2 silver badges9 bronze badges

1

Понравилась статья? Поделить с друзьями:
  • Bash error dev null
  • Bash error codes
  • Bash echo write error invalid argument
  • Bash disable error output
  • Bash deb команда не найдена как исправить