Skip to content

RPN Calculator in Bash

This Bash script implements a Reverse Polish Notation (RPN) calculator. It reads input from standard input, interprets each line as an RPN expression, and evaluates the expressions by performing arithmetic calculations.


Implementation Details

  • The script uses the IFS (Internal Field Separator) variable to define delimiters for splitting strings into words, considering space and tab characters as delimiters by default.
  • Input is read from standard input using the read command, storing each line in the expression array.
  • Empty lines are skipped, and the script moves to the next line.
  • Tokens in the expression array are processed sequentially:
  • Numbers are validated using regular expressions, and if valid, are pushed onto the stack.
  • Operators (+, -, *, /) require sufficient operands. If valid, the calculation is performed and the result is updated in the array.
  • The script relies on the bc command-line utility for performing floating-point arithmetic.
  • If the final expression array has exactly one element, it is the result. Otherwise, an error message is displayed.

The full reverse notation script

#!/usr/bin/env bash

IFS=$' \t' # Set the Internal Field Separator (IFS) to include space and tab characters
while read -r -a expression; do
        ((n = ${#expression[*]}))
        if [ $n -eq 0 ]; then continue; fi
        ((i = 0))
        while :; do
                element=${expression[i]}
                if [[ $element =~ ^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)$ ]]; then
                        ((++i)) # Increment the index to move to the next element
                elif [[ $element =~ ^[-+*/]$ ]]; then
                        if [ $i -lt 2 ]; then break; fi
                        case $element in
                        "+") expression[i - 2]=$(echo "${expression[i - 2]} + ${expression[i - 1]}" | bc) ;;          
                        "-") expression[i - 2]=$(echo "${expression[i - 2]} - ${expression[i - 1]}" | bc) ;;          
                        "*") expression[i - 2]=$(echo "${expression[i - 2]} * ${expression[i - 1]}" | bc) ;;          
                        "/") expression[i - 2]=$(echo "scale=2; ${expression[i - 2]} / ${expression[i - 1]}" | bc) ;; 
                        esac
                        expression[i]=
                        ((--i)) 
                        expression[i]=
                        ((n -= 2))                      
                        expression=("${expression[@]}") 
                else
                        break
                fi
                if [ $i -eq $n ]; then break; fi
        done
        if [ $i -eq $n ] && [ $n -eq 1 ]; then
                echo "${expression}" # Output the result
        else
                echo 'error' # Output error message
        fi
done

Examples Usage

Addition

./rpn_calculator.sh
5 2 +
7

Subtraction

./rpn_calculator.sh
8 3 -
5

Multiplication

./rpn_calculator.sh
4 6 *
24

Division

./rpn_calculator.sh
10 2 /
5.00

Invalid expression

./rpn_calculator.sh
5 +
error