简体   繁体   中英

Linux shell negative values print problem

operation () {
   operator=${exp:1:1} # 2nd character / 1st is ${words:0:1} 

   # Read into an array as tokens separated by IFS
   IFS="$operator"
   read -ra array <<< "$exp" # -ra = raw input array
   a=array[0]
   b=array[1]
   # https://www.computerhope.com/unix/bash/read.htm

   if [ "$operator" == "+" ]; then
    operation=$((a+b))
   fi
   if [ "$operator" == "-" ]; then
    operation=$((a+b)) # => ' 1'
    operation=`expr a-b` # => ' 1'
   fi
   if [ "$operator" == "*" ]; then
    operation=$((a*b))
   fi
   if [ "$operator" == "/" ]; then
    operation=$((a/b))
   fi
   # https://www.tutorialsandyou.com/bash-shell-scripting/bash-arithmetic-operations-11.html
   echo $((operation))
}
exp='2-3'
operation $exp 

Everything(almost) works fine, just when making the subtraction operation=$((a+b)) or operation=`expr ab` I cannot print in anyway minus('-') instad of space(' '), the (-) sign it is been replaced by space. In this example I get ' 1' instead of '-1' .

Why is this happening?

use space around -:

exp=' 2 - 3 '

or

operation = expr a - b

or

COUNT="expr $FIRSTV - $SECONDV"

also see this [ link ] 1

I guess you meant to use - if operator is a minus sign:

if [ "$operator" == "-" ]; then
    operation=$((a - b)) # => ' 1'
fi

There are 2 problems with this script. First, arrays elements are not referenced like array[0] is in C but ${name[subscript]} as it says in man bash:

Any element of an array may be referenced using ${name[subscript]}.

So it should be:

a=${array[0]}
b=${array[1]}

Second, $((var)) should only be used for arithmetic. If you want to print contents of variable just do:

echo "$operation"

All in all, your script should be:

#!/usr/bin/env bash

operation () {
    operator=${exp:1:1} # 2nd character / 1st is ${words:0:1}

    # Read into an array as tokens separated by IFS
    IFS="$operator"
    read -ra array <<< "$exp" # -ra = raw input array
    a=${array[0]}
    b=${array[1]}
    # https://www.computerhope.com/unix/bash/read.htm

    if [ "$operator" == "+" ]; then
        operation=$((a+b))
    fi
    if [ "$operator" == "-" ]; then
        operation=$((a - b))
    fi
    if [ "$operator" == "*" ]; then
        operation=$((a*b))
    fi
    if [ "$operator" == "/" ]; then
        operation=$((a/b))
    fi
    # https://www.tutorialsandyou.com/bash-shell-scripting/bash-arithmetic-operations-11.html
    echo "$operation"
}
exp='2-3'
operation $exp

Usage:

$ ./script.sh
-1

We're missing some context here:

  • This a=array[0] is only correct if declare -ia .
  • What is exp ?

But the problem is a simple matter of lack of quoting:

$ IFS="-"
$ operation="-6"
$ echo $((operation))
 6
$ echo "$((operation))"
-6

This is entirely due to the IFS value. bash gets echo -6 and translates that into echo "" 6 with the empty string to the left of the - delimiter.

Within quotes, word splitting is not performed.

Behaviour documented in 3.5.7 Word Splitting in the manual.


You can set IFS only for the duration of the read command so it does not affect the rest of the script:

$ exp="4-5"
$ IFS=- read -ra array <<<"$exp"
$ declare -p array
declare -a array=([0]="4" [1]="5")
$ printf "%q\n" "$IFS"
$' \t\n'
  1. I remove this line operation='expr ab' # => ' 1'
  2. In this line operation=$((a+b)) # => ' 1' you must use - instead +:
  3. For output use "" around the variables :

echo "$((operation))"

This code work properly:

operation () {
   operator=${exp:1:1} # 2nd character / 1st is ${words:0:1} 

   # Read into an array as tokens separated by IFS
   IFS="$operator"
   read -ra array <<< "$exp" # -ra = raw input array
   a=array[0]
   b=array[1]
   
   # https://www.computerhope.com/unix/bash/read.htm

   if [ "$operator" == "+" ]; then
    operation=$((a+b))
   fi
   if [ "$operator" == "-" ]; then
    operation="$((a-b))"
   fi
   if [ "$operator" == "*" ]; then
    operation=$((a*b))
   fi
   if [ "$operator" == "/" ]; then
    operation=$((a/b))
   fi
   # https://www.tutorialsandyou.com/bash-shell-scripting/bash-arithmetic-operations-11.html
   echo "$((operation))"
}
exp='2-3'
operation $exp 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM