-1

I'm working on a simple script that accepts multiple command line arguemnts in an order:

#!/bin/bash

function arg_parser () {
while [[ $# != 0 ]] ; do
  case "$1" in
    --one)
      varone="$2"
      ;;
    --two)
      vartwo="$2"
      ;;
    --three)
      varthree="$2"
      ;;
    --four)
      varfour="$2"
      ;;
    --five)
      varfive="$2"
      ;;
  esac
  shift
done
}

arg_parser "$@"

echo $varone
echo $vartwo
echo $varthree
echo $varfour
echo $varfive

Then run it:

./test.sh --one testone --three testthree --two testtwo --five "test five" --four "$$$$"
testone
testtwo
testthree
793793
test five

Notice how --four returns "793793" and not "$$$$"? Does anyone know why this is happening and/or how the script can be improved to prevent this from happening?

marked as duplicate by jasonwryan, Isaac, G-Man, RalfFriedl, roaima Dec 4 '18 at 8:51

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    Your quoting is broken: that is Process ID (PID) of the script itself. – jasonwryan Dec 3 '18 at 22:02
  • sorry, where is it broken exactly? – user324071 Dec 3 '18 at 22:04
  • " expands the variable $$: you want single quotes: '. – jasonwryan Dec 3 '18 at 22:04
  • oooh, i see. so this cant be resolved in the script to make it possible to use "$$$$" as an argument? – user324071 Dec 3 '18 at 22:06
  • 1
    The expansion happens before it is passed to your script. You have to use single quotes '$$$$' if you want literal $ characters passed to your script. – jordanm Dec 3 '18 at 22:11
0

$$ is a special variable that expands to the process id of the shell, in this case on the command line before your script even starts. Try something like echo $$. You'll need to escape the dollar signs with backslashes or put them in single quotes to not have them expand, i.e. echo '$$$$'.

The double quotes don't help, they'll just prevent word splitting of the expanded value, just like with regular variables ($foo vs. "$foo").

Also, in your loop, you shift only once even in the cases where you use the second argument too. This means that the arguments to your options are also processed as options themselves:

$ ./test.sh --one --two --three --four --five xyz
--two
--three
--four
--five
xyz

If you don't want that, you'll need to shift an additional time after using $2:

while [[ "$#" != 0 ]] ; do
  case "$1" in
    --one)
      varone="$2"
      shift
      ;;
    --two)
      vartwo="$2"
      shift
      ;;
    # ...
  esac
  shift
done

Not the answer you're looking for? Browse other questions tagged or ask your own question.