aleksandr barakin
aleksandr barakin

Reputation: 551

Inline array substitution

I have file with a few lines:

x 1
y 2
z 3 t

I need to pass each line as paramater to some program:

$ program "x 1" "y 2" "z 3 t"

I know how to do it with two commands:

$ readarray -t a < file
$ program "${a[@]}"

How can i do it with one command? Something like that:

$ program ??? file ???

Upvotes: 0

Views: 65

Answers (2)

ErikMD
ErikMD

Reputation: 14723

The (default) options of your readarray command indicate that your file items are separated by newlines.

So in order to achieve what you want in one command, you can take advantage of the special IFS variable to use word splitting w.r.t. newlines (see e.g. this doc) and call your program with a non-quoted command substitution:

IFS=$'\n'; program $(cat file)

As suggested by @CharlesDuffy:

  1. you may want to disable globbing by running beforehand set -f, and if you want to keep these modifications local, you can enclose the whole in a subshell:

    ( set -f; IFS=$'\n'; program $(cat file) )
    
  2. to avoid the performance penalty of the parens and of the /bin/cat process, you can write instead:

    ( set -f; IFS=$'\n'; exec program $(<file) )
    

    where $(<file) is a Bash equivalent to to $(cat file) (faster as it doesn't require forking /bin/cat), and exec consumes the subshell created by the parens.

    However, note that the exec trick won't work and should be removed if program is not a real program in the PATH (that is, you'll get exec: program: not found if program is just a function defined in your script).

Upvotes: 1

Mike Q
Mike Q

Reputation: 7327

Passing a set of params should be more organized : In this example case I'm looking for a file containing chk_disk_issue=something etc.. so I set the values by reading a config file which I pass in as a param.

# -- read specific variables from the config file (if found) --
if [ -f "${file}" ] ;then
    while IFS= read -r line ;do
        if ! [[ $line = *"#"* ]]; then
            var="$(echo $line | cut -d'=' -f1)"
            case "$var" in
                chk_disk_issue)
                    chk_disk_issue="$(echo $line | tr -d '[:space:]' | cut -d'=' -f2 | sed 's/[^0-9]*//g')"
                ;;
                chk_mem_issue)
                    chk_mem_issue="$(echo $line | tr -d '[:space:]' | cut -d'=' -f2 | sed 's/[^0-9]*//g')"
                ;;
                chk_cpu_issue)
                    chk_cpu_issue="$(echo $line | tr -d '[:space:]' | cut -d'=' -f2 | sed 's/[^0-9]*//g')"
                ;;
            esac
        fi
    done < "${file}"
fi

if these are not params then find a way for your script to read them as data inside of the script and pass in the file name.

Upvotes: 0

Related Questions