1

I have a BASH script to add two numbers where I want to pass two numbers via command line arguments.

cat add.sh

a=$1
echo "exit status for a " $?

b=$2
echo "exit status for b " $?

sum=`expr $a + $b`
echo "exit status for sum " $?

echo "result is " $sum
echo "exit status for result " $?

When I run the above script without providing any value or arguments, I am getting following output.

$ ./add.sh 
exit status for a  0  (expecting 1 here)
exit status for b  0 (expecting 1 here)
expr: syntax error
exit status for sum  2  
result is 
exit status for result  0 (expecting 1 here)

I am expecting value of $? as 1 when I am not providing any arguments via command line, so it must be an error for assigning value of a and b.

Can anyone explain why a=$1 or b=$2 doesn't return exit status 1 when NO value is supplied via command line? Why it returns 0 ?

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
bholanath
  • 1,699
  • 1
  • 22
  • 40
  • 1
    Because parameter expansion on an unset variable is not an error by default. So unless you `set -u` these are valid, see [`man set`](https://ss64.com/bash/set.html) – tomix86 Jan 14 '18 at 19:15
  • `0` is success. Why would you expect anything else? – Charles Duffy Jan 14 '18 at 19:15
  • Shell variables always have a value; if they're unset then they're just empty. If you want to test whether a variable exists, use `test` / `[ -n $variable ]`. – L3viathan Jan 14 '18 at 19:15
  • BTW, `expr` is something that only exists today for compatibility with 1970s-era shells. Use POSIX math syntax, `sum=$(( a + b ))`, instead. – Charles Duffy Jan 14 '18 at 19:16
  • ...also, your expansions should be **inside** quotes. Thus, `echo "exit status for a: $?"`. With `$?` unquoted, it's subject to the state of `IFS`, so if you had `IFS=0`, then `echo $?` would just print an exit line (when it would otherwise print 0). There are other corner cases and bugs as well that can be caused by unquoted expansion -- that's just an easy-to-demo one. – Charles Duffy Jan 14 '18 at 19:16
  • @CharlesDuffy I am expecting 0 as I said I haven't pass any argument via command line, so assignment fails. – bholanath Jan 14 '18 at 19:17
  • Why would that be a failure? If there is no `$1`, then it expands to an empty string. Assigning an empty string is a legit operation. – Charles Duffy Jan 14 '18 at 19:17
  • Only when you try to assign to a `readonly` variable, you will get `1`. – PesaThe Jan 14 '18 at 19:18
  • @PesaThe, how to make that ? readonly means constant value ? – bholanath Jan 14 '18 at 19:19
  • 1
    BTW, did you read the very first comment, by tomix86? It would seem to give you **exactly** what you're asking for (though I don't advise its use). See also [BashFAQ #112](http://mywiki.wooledge.org/BashFAQ/112). – Charles Duffy Jan 14 '18 at 19:19
  • 1
    That's really not what you want to do here. You want to check whether you have passed enough arguments, with `(( $# >= 2 ))` for example. – PesaThe Jan 14 '18 at 19:20
  • 1
    Or `a=${1?First argument is mandatory}; b=${2?Second argument is mandatory}` – Charles Duffy Jan 14 '18 at 19:21
  • @CharlesDuffy, I have tried to run the above script after set -u command, but still I am getting same output. – bholanath Jan 14 '18 at 19:21
  • 3
    Run the script *after* `set -u`? No. Put `set -u` *in* the script. – Charles Duffy Jan 14 '18 at 19:22
  • @PesaThe, I want to modify this script so in case I have not provide value of either a or b or both it should be an error. – bholanath Jan 14 '18 at 19:23
  • BTW, as an aside -- using `.sh` extension for a bash script is bad form -- it falsely implies that the script can be run with `sh` (an interpreter which is only guaranteed to provide POSIX compatibility, not bash extensions), and executables on UNIX don't have extensions anyhow (the interpreter to use for a script is determined by the shebang line -- ie. `#!/usr/bin/env bash` at the beginning of the file; this also has the advantage that you can rewrite a program in a different language and not need to modify other software that calls it). – Charles Duffy Jan 14 '18 at 19:27
  • @CharlesDuffy, adding set -u inside script works as my expectation. Thank you. – bholanath Jan 14 '18 at 19:27
  • @bholanath still you should read all the resources mentioned here, BashFAQ and related SO questions. This is **really** not the proper approach to checking whether a parameter was provided when calling the script. – tomix86 Jan 14 '18 at 19:30
  • (BTW, note the edit to make the title a self-contained sentence that reflects the specific question being asked -- when a title refers to "this" or "these", it means someone can't tell what is being asked without first clicking through; that should be avoided wherever possible). – Charles Duffy Jan 14 '18 at 19:37
  • @CharlesDuffy, I agree with you. Now the edited title reflects the correct question to be answered. I will adopt this technique in future. – bholanath Jan 14 '18 at 19:41

0 Answers0