In bash I am calling function:

myFunction "1 2"
        echo "$1"
        echo "$2"

this prints me "1 2" and empty row. How I can parse arguments so it will print on one row 1 and on another 2 ? I can not call myFunction "1" "2" because arguments are stored in some other variable


Try like this,

        echo "$1"
        echo "$2"

myFunction 1 2
  • ah ok lol I am so dumb thx a lot – hudi Oct 3 '18 at 14:29
  • 1
    You said in your question that you can not call myFunction "1" "2", yet that is how this answer solved the problem... – Jeff Schaller Oct 3 '18 at 15:23

Sounds like you want to split the first argument your function receives on space characters. For that, you could use the split+glob operator after having configured the split part to use space as the delimiter and disabled the glob part:

myfunction() {
  local -       # make changes to options local to the function.
                # needs bash 4.4 or newer.
  local IFS=' ' # split on space only
  set -o noglob # disable glob part
  set -- $1     # split+glob invoked on $1 by leaving that $1 unquoted,
                # result stored in $1, $2... using set --
  printf '%s\n' "$1"
  printf '%s\n' "$2"
myfunction "1 2"

That's the same as splitting any variable on spaces. Use word splitting or read:

With word splitting:

var="foo bar"
set -f              # disable globbing
IFS=' '             # make sure IFS contains (just) a space
printf "%s\n" $var  

With read, for a standard shell (if you know there's only two pieces to split into):

var="foo bar"
IFS=' ' read a b <<EOF
printf "%s\n" "$a" "$b" 

The same with a here-string (Bash/ksh/zsh):

var="foo bar"
IFS=' ' read a b <<< "$var"
printf "%s\n" "$a" "$b" 

With read -a in Bash, or read -A in ksh/zsh, you can split the string to an arbitrary number of pieces and put them in an array:

var="foo bar"
IFS=' ' read -a arr <<< "$var"     # Bash
printf "%s\n" "${arr[@]}"

In all of the above, you can use $1 in place of $var as usual.

The variants with read also assume the string doesn't contain multiple lines.

However, in Bash you can also split a multi-line string to an array using any whitespace as separator:

IFS=$' \t\n' read -d '' -a arr <<< "$var"

Of course if you have the string in a variable outside the function, and run myFunction $var, the variable will be split to multiple arguments before the function runs.

  • I prefer set -o noglob over set -f as set -f means something different in zsh (though is not needed there, and set -f would be harmless) – Stéphane Chazelas Oct 3 '18 at 14:35
  • @StéphaneChazelas, right you are, as always. I didn't realize zsh had changed the meaning of set -f, thanks. – ilkkachu Oct 3 '18 at 14:42
  • Note that it's read -A in ksh93 and zsh. Not sure why bash maintainers chose to break compatibility with them when they added -a years later – Stéphane Chazelas Oct 3 '18 at 14:46
  • Technically, it's the Bourne shell that changed the meaning of -f. zsh gets it from csh which added -f before the Bourne shell. set -f behaves like in the Bourne shell in zsh when in sh emulation. – Stéphane Chazelas Oct 3 '18 at 14:52
  • @StéphaneChazelas, ah, that sounds more sensible, actually. – ilkkachu Oct 3 '18 at 14:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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