Why is $1 in a function not printing the script's first argument?

19,871

Solution 1

Positional parameters refer to the script's arguments in the main level of the script, but to function arguments in function body. So

print_something Something

would actually print Something.

If you want to pass the script's arguments to a function, you must do that explicitly. Use

print_something "$1"

to pass the first argument, or

print_something "$@"

to pass all of them, though the function in example only uses the first one.

Solution 2

This is because a called function gets its own set of positional parameters, independent of the parent's / caller's set. Try

print_something "$1"

(and echo "$1", or even better printf '%s\n' "$1", remember to quote parameter expansions and that echo can't be used for arbitrary data).

Share:
19,871

Related videos on Youtube

pietro letti
Author by

pietro letti

curious, very curious. self-taught. toward LPIC-1 system administrator.

Updated on September 18, 2022

Comments

  • pietro letti
    pietro letti almost 2 years

    Why doesn't echo $1 print $1 in this simple bash script?

    #!/bin/bash
    # function.sh
    print_something () {
    echo $1
    }
    print_something
    
    $ ./function.sh 123  -> why doesn't it print '123' as a result?
    
    • Rui F Ribeiro
      Rui F Ribeiro almost 6 years
      because you forgot the $1 when calling print_something. Please try to include text in the question and not in the title.
    • pietro letti
      pietro letti almost 6 years
      thanks. What should be the echo argument if I need to insert in the script the commands: print_something "$1"; print_something "$2"; and maybe more?
    • pipe
      pipe almost 6 years
      When I saw this in HNQ I thought you were printing dollar-bills and hoped to read some juicy story about how your printer detects that you're printing fake money.
    • Codingale
      Codingale almost 6 years
      @pipe I've had that happen to me before, for some reason it refuses to print anything not just the ones with the anti-printing preventions.
  • RudiC
    RudiC almost 6 years
    You need to become clearer what you are talking about. The caller's $1 is generally different from the function's $1, although they CAN become the same if used like proposed above. If I get you right, the echo can stay the same (echo $1) when the function is called with single parameters (print_something $2 takes the caller's $1 and "makes" it $1 inside the function)
  • Stéphane Chazelas
    Stéphane Chazelas almost 6 years
    Using echo $1 doesn't make sense unless you want $1 to be treated as a $IFS-delimited list of file patterns to expand. echo "$1" would make more sense, though would not output the content of $1 for values of $1 like -nene, -EE...
  • Kusalananda
    Kusalananda almost 6 years
    Passing "$@" to print_something, as it's currently written, would still only print the first of the arguments though.
  • weirdan
    weirdan almost 6 years
    But the point was to show how to pass all arguments, I presume. The fact that the function, as it stands, only uses the first of its arguments is a bit irrelevant.
  • Kusalananda
    Kusalananda almost 6 years
    Well, just thinking there's no point in passing all the arguments along if only the first one is being used.
  • allo
    allo almost 6 years
    @Kusalananda "$@" has quotes, making it a single argument to print_something.
  • Kusalananda
    Kusalananda almost 6 years
    @allo No. "$*" would be a single string (joined on the first character of $IFS) while "$@" would be a list of individually quoted elements.
  • ygreaney
    ygreaney almost 6 years
    @Kusalananda the point of telling someone who wants to pass the command-line parameters to a function to use "$@", even if in this case there is only one such parameter, is to cover all such cases. If the OP decides to add a second parameter, there's nothing to change in the function invocation. And everyone else who reads this will learn the right way to do it to avoid having to re-do it later, too.
  • Admin
    Admin about 2 years
    I think you are saying the opposite while meaning the correct. The positional arguments are those passed to that function, not that in the global scope of the whole script. For that reason print_something cannot see the $1 of the script, as it is not passed to the function.
  • Admin
    Admin about 2 years
    «The positional arguments are those passed to that function, not that in the global scope» — They are both positional ($N), but they do refer to different data, depending on the scope