A $(( expression )) bug?


 
Thread Tools Search this Thread
Top Forums UNIX for Advanced & Expert Users A $(( expression )) bug?
# 1  
Old 09-28-2016
A $(( expression )) bug?

This is for the big guns...
I have been modifying AudioScope.sh to bring it inline with more current practices.
I hit a bug which IS not present in the original code but was after modification.
Shell check first:-
Code:
#!/bin/sh
txt="1234567890"
echo "$(( $txt ))"
echo "$(( ${#txt} - 1 ))"
echo "$(( #txt - 1 ))"

ERROR WINDOW.

$ shellcheck myscript
 
Line 3:
echo "$(( $txt ))"
          ^-- SC2004: $/${} is unnecessary on arithmetic variables.

$

Here is a longhand input to the bash version on 'sh' and yes I did have this inside my code, and what a RPITA it was too. (This also fails inside the version of bash for OSX 10.7.5; I don't know about current versions as i don't have them.)
Code:
Last login: Wed Sep 28 09:36:29 on ttys000
AMIGA:barrywalker~> sh
AMIGA:barrywalker~> txt="1234567890"
AMIGA:barrywalker~> echo "$(( $txt ))"
1234567890
AMIGA:barrywalker~> echo "$(( ${#txt} - 1 ))"
9
AMIGA:barrywalker~> echo "$(( #txt - 1 ))"
sh: bad substitution: no closing `)' in "$(( #txt - 1 ))"
AMIGA:barrywalker~> _

Either "$/${}" is needed or it is not, which is it?
From now on I will be using $ and ${} as I don't want this aggro again...
This User Gave Thanks to wisecracker For This Post:
# 2  
Old 09-28-2016
The
Quote:
Arithmetic Expansion
Arithmetic expansion allows the evaluation of an arithmetic expression and the substitution of the result. The format for arithmetic expansion is:

$((expression))

The old format $[expression] is deprecated and will be removed in upcoming versions of bash.

The expression is treated as if it were within double quotes, but a double quote inside the parentheses is not treated specially. All tokens in the expression undergo parameter and variable expansion, command substitution, and quote removal.
(c.f. man bash) is available in recent shells only, not in sh. As you can see, variable expansion is done implicitly, no $ nor ${} necessary. Your message above is informative, not an error.

Last edited by RudiC; 09-28-2016 at 01:40 PM.. Reason: added the man bash reference
# 3  
Old 09-28-2016
It fails on ksh too!
Code:
Last login: Wed Sep 28 10:21:58 on ttys000
AMIGA:barrywalker~> ksh
AMIGA:uw> txt="1234567890"
AMIGA:uw> echo "$(( ${#txt} - 1 ))"
9
AMIGA:uw> echo "$(( #txt - 1 ))"
ksh:  #txt - 1 : arithmetic syntax error
AMIGA:uw> exit 
AMIGA:barrywalker~> _

---------- Post updated at 11:09 AM ---------- Previous update was at 10:30 AM ----------

And the WRONG answer with zsh!
Code:
AMIGA:barrywalker~> zsh
AMIGA:\u\w> zsh --version
zsh 4.3.11 (i386-apple-darwin11.0)
AMIGA:\u\w> txt="1234567890"
AMIGA:\u\w> echo "$(( ${#txt} - 1 ))"
9
AMIGA:\u\w> echo "$(( #txt - 1 ))" 
48
AMIGA:\u\w> _

EDIT:-
This should have been a new post but was added to this one, no idea why!

Last edited by wisecracker; 09-28-2016 at 07:11 AM.. Reason: See above.
# 4  
Old 09-28-2016
In an arithmetic evaluation, the value of a variable can be specified by expanding the variable (i.e. $var or ${var}) or by just giving the variable name (i.e. var). But the expression that is the numeric evaluation of the length of the string that is the value of a variable must use the expansion of the variable that produces that number (i.e. ${#var}); you cannot skip the ${ and } when you are using shell variable expansion operators like ${#var} or ${var%%pattern} or ${var:offset:length}.
# 5  
Old 09-28-2016
Quote:
Originally Posted by Don Cragun
In an arithmetic evaluation, the value of a variable can be specified by expanding the variable (i.e. $var or ${var}) or by just giving the variable name (i.e. var). But the expression that is the numeric evaluation of the length of the string that is the value of a variable must use the expansion of the variable that produces that number (i.e. ${#var}); you cannot skip the ${ and } when you are using shell variable expansion operators like ${#var} or ${var%%pattern} or ${var:offset:length}.
OK, I'll go with that BUT, and a big but, why does Shell Check echo "$(( #txt - 1 ))" NOT come up with a syntax error knowing from the various scenarios that it does?
Should there not be a warning saying so. Note that in the Shell Check example I was using the worst case sh . Tested on the others gave errors or incorrect results too.
On reading RudiC's post it looks as though it SHOULD work but obviously it doesn't, or I am misinterpreting it?
Anyhow thanks, but I will keep '$/${}' in all cases just to be on the safe side.
# 6  
Old 09-28-2016
Quote:
Originally Posted by wisecracker
OK, I'll go with that BUT, and a big but, why does Shell Check echo "$(( #txt - 1 ))" NOT come up with a syntax error knowing from the various scenarios that it does?
Should there not be a warning saying so. Note that in the Shell Check example I was using the worst case sh . Tested on the others gave errors or incorrect results too.
On reading RudiC's post it looks as though it SHOULD work but obviously it doesn't, or I am misinterpreting it?
Anyhow thanks, but I will keep '$/${}' in all cases just to be on the safe side.
There is something in what RudiC quoted in post #2 that says that the string ${#variable_name} inside an arithmetic expansion will undergo parameter expansion resulting in a number that is the number of characters in the string to which $variable_name expands. (I.e., All tokens in the expression undergo parameter and variable expansion, command substitution, and quote removal.)

There is nothing in what RudiC quoted in post #2 that says that the string #variable_name inside an arithmetic expansion should have any meaning (and I don't know of any shells where it does).

There is something in what RudiC quoted in post #2 that says that the strings $variable_name and ${variable_name} inside an arithmetic expansion will expand to the string assigned to that variable. (I.e., All tokens in the expression undergo parameter and variable expansion, command substitution, and quote removal.)

There is nothing in what RudiC quoted in post #2 that says that the string variable_name inside an arithmetic expansion will expand to the string that has been assigned to that variable. But, in addition to what RudiC quoted, the latest version of the standard also states the following requirement for arithmetic expansions:
Quote:
If the shell variable x contains a value that forms a valid integer constant, optionally including a leading <plus-sign> or <hyphen-minus>, then the arithmetic expansions "$((x))" and "$(($x))" shall return the same value.
and I don't know of any shell that performs arithmetic expansions that does not also provide this shortcut.

I make absolutely no comment as to why shellcheck seems to think that $((#variable_name)) and $(( #variable_name - 1 )) are not errors. You would have to ask the developers or maintainers of that code why they do not flag these constructs as errors in arithmetic expressions in shell scripts.
This User Gave Thanks to Don Cragun For This Post:
# 7  
Old 09-28-2016
Thanks Don...

I will attempt to get in touch with the Shell Check developers.
Consider this thread solved.

EDIT:-
As an addendum...
I have left a message on their bug report board...

Thanks for the heads up Don.

Last edited by wisecracker; 09-28-2016 at 01:28 PM.. Reason: See above...
Login or Register to Ask a Question

Previous Thread | Next Thread

8 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Why Relational Expression is Writing to a Expression?

Hello All, Not sure why this is happening... When the following If Statement is evaluated for some reason it is creating a file in the CWD called '0'. I've seen this happen before, just not in an If Statement... CODE: if then DIR_NAME="$1" DIR_SIZE=0 STATUS="" else... (3 Replies)
Discussion started by: mrm5102
3 Replies

2. UNIX for Advanced & Expert Users

sed: -e expression #1, char 0: no previous regular expression

Hello All, I'm trying to extract the lines between two consecutive elements of an array from a file. My array looks like: problem_arr=(PRS111 PRS213 PRS234) j=0 while } ] do k=`expr $j + 1` sed -n "/${problem_arr}/,/${problem_arr}/p" problemid.txt ---some operation goes... (11 Replies)
Discussion started by: InduInduIndu
11 Replies

3. Programming

Perl: How to read from a file, do regular expression and then replace the found regular expression

Hi all, How am I read a file, find the match regular expression and overwrite to the same files. open DESTINATION_FILE, "<tmptravl.dat" or die "tmptravl.dat"; open NEW_DESTINATION_FILE, ">new_tmptravl.dat" or die "new_tmptravl.dat"; while (<DESTINATION_FILE>) { # print... (1 Reply)
Discussion started by: jessy83
1 Replies

4. Shell Programming and Scripting

Integer expression expected: with regular expression

CA_RELEASE has a value of 6. I need to check if that this is a numeric value. if not error. source $CA_VERSION_DATA if * ] then echo "CA_RELESE $CA_RELEASE is invalid" exit -1 fi + source /etc/ncgl/ca_version_data ++ CA_PRODUCT_ID=samxts ++ CA_RELEASE=6 ++ CA_WEEK_NO=7 ++... (3 Replies)
Discussion started by: ketkee1985
3 Replies

5. UNIX for Dummies Questions & Answers

where's the bug?

#!/bin/bash if then #echo "infinite loop" exit 0 fi when I run this file I get the following error: ./test_infinite_loop: line 5: syntax error near unexpected token `fi' ./test_infinite_loop: line 5: `fi' :confused: (4 Replies)
Discussion started by: jon80
4 Replies

6. AIX

bug in 43 ???

xxxxserver# lsattr -El inet0 | grep 255.240.0.0,32.224.0.0,32.78.120.254 | grep '.40' route net,-hopcount,1,-netmask,255.240.0.0,32.224.0.0,32.78.120.254 How this is possible? (1 Reply)
Discussion started by: itik
1 Replies

7. Programming

error: initializer expression list treated as compound expression

I had seen this error for the first time ..... error: initializer expression list treated as compound expression please help.... (12 Replies)
Discussion started by: arunchaudhary19
12 Replies

8. Shell Programming and Scripting

Regular Expression + Aritmetical Expression

Is it possible to combine a regular expression with a aritmetical expression? For example, taking a 8-numbers caracter sequece and casting each output of a grep, comparing to a constant. THX! (2 Replies)
Discussion started by: Z0mby
2 Replies
Login or Register to Ask a Question