在 bash 中捕获多行输出作为数组

如果 inner.sh

#...
echo first
echo second
echo third

outer.sh

var=`./inner.sh`
# only wants to use "first"...

如何用空格分割 var

94637 次浏览

Try this:

var=($(./inner.sh))


# And then test the array with:


echo ${var[0]}
echo ${var[1]}
echo ${var[2]}

Output:

first
second
third

Explanation:

  • You can make an array in bash by doing var=(first second third), for example.
  • $(./inner.sh) runs the inner.sh script, which prints out first, second, and third on separate lines. Since we don't didn't put double quotes around $(...), they get lumped onto the same line, but separated by spaces, so you end up with what it looks like in the previous bullet point.

You're not splitting on whitespaces but rather on newlines. Give this a whirl:

IFS=$'
'


var=$(./echo.sh)
echo $var | awk '{ print $1 }'
unset IFS

Don't forget the builtin mapfile. It's definitely the most efficient in your case: If you want to slurp the whole file in an array, the fields of which will be the lines output by ./inner.sh, do

mapfile -t array < <(./inner.sh)

Then you'll have the first row in ${array[0]}, etc...

For more info on this builtin and all the possible options:

help mapfile

If you just need the first line in a variable called firstline, do

read -r firstline < <(./inner.sh)

These are definitely the most efficient ways!

This small benchmark will prove it:

$ time mapfile -t array < <(for i in {0..100000}; do echo "fdjsakfjds$i"; done)


real    0m1.514s
user    0m1.492s
sys 0m0.560s
$ time array=( $(for i in {0..100000}; do echo "fdjsakfjds$i"; done) )


real    0m2.045s
user    0m1.844s
sys 0m0.308s

If you only want the first word (with space delimiter) of the first line output by ./inner.sh, the most efficient way is

read firstword _ < <(./inner.sh)