Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

minimal typing command line calculator - tcsh vs bash

I like to have a command-line calculator handy. The requirements are:

  • Support all the basic arithmetic operators: +, -, /, *, ^ for exponentiation, plus parentheses for grouping.
  • Require minimal typing, I don't want to have to call a program interact with it then asking it to exit.
  • Ideally only one character and a space in addition to the expression itself should be entered into the command line.
  • It should know how to ignore commas and dollar (or other currency symbols) in numbers to allow me to copy/paste from the web without worrying about having to clean every number before pasting it into the calculator
  • Be white-space tolerant, presence or lack of spaces shouldn't cause errors
  • No need for quoting anything in the expression to protect it from the shell - again for the benefit of minimal typing

Since tcsh supports alias positional arguments, and since alias expansion precedes all other expansions except history-expansion, it was straight forward to implement something close to my ideal in tcsh.

I used this:

alias C 'echo '\''\!*'\'' |tr -d '\'',\042-\047'\'' |bc -l'

Now I can do stuff like the following with minimal typing:

# the basic stuff:
tcsh>  C 1+2
3

# dollar signs, multiplication, exponentiation:
tcsh>  C $8 * 1.07^10
15.73721085831652257992

# parentheses, mixed spacing, zero power:
tcsh>  C ( 2+5 ) / 8 * 2^0
.87500000000000000000

# commas in numbers, no problem here either:
tcsh>  C 1,250.21 * 1.5
1875.315

As you can see there's no need to quote anything to make all these work.

Now comes the problem. Trying to do the same in bash, where parameter aliases aren't supported forces me to implement the calculator as a shell function and pass the parameters using "$@"

function C () { echo  "$@" | tr -d ', \042-\047' | bc -l; }

This breaks in various ways e.g:

# works:
bash$  C 1+2
3

# works:
bash$  C 1*2
2

# Spaces around '*' lead to file expansion with everything falling apart:
bash$  C  1 * 2
(standard_in) 1: syntax error
(standard_in) 1: illegal character: P
(standard_in) 1: illegal character: S
(standard_in) 1: syntax error
...

# Non-leading parentheses seem to work:
bash$  C  2*(2+1)
6

# but leading-parentheses don't:
bash$  C  (2+1)*2
bash: syntax error near unexpected token `2+1'

Of course, adding quotes around the expression solves these issues, but is against the original requirements.

I understand why things break in bash. I'm not looking for explanations. Rather, I'm looking for a solution which doesn't require manually quoting the arguments. My question to bash wizards is is there any way to make bash support the handy minimal typing calculator alias. Not requiring quoting, like tcsh does? Is this impossible? Thanks!

like image 353
arielf Avatar asked Feb 19 '13 19:02

arielf


1 Answers

If you're prepared to type C Enter instead of C Space, the sky's the limit. The C command can take input in whatever form you desire, unrelated to the shell syntax.

C () {
  local line
  read -p "Arithmetic: " -e line
  echo "$line" | tr -d \"-\', | bc -l
}

In zsh:

function C {
  local line=
  vared -p "Arithmetic: " line
  echo $line | tr -d \"-\', | bc -l
}

In zsh, you can turn off globbing for the arguments of a specific command with the noglob modifier. It is commonly hidden in an alias. This prevents *^() from begin interpreted literally, but not quotes or $.

quickie_arithmetic () {
  echo "$*" | tr -d \"-\', | bc -l
}
alias C='noglob quickie_arithmetic'
like image 184
Gilles 'SO- stop being evil' Avatar answered Sep 19 '22 18:09

Gilles 'SO- stop being evil'