Reading Command Output Into an Array
In this page:
mapfile / readarray Basics
mapfile -t arr reads standard input line by line and stores each line as one element of arr, with -t stripping the trailing newline from each. This is the cleanest way to turn multi-line text into an array without manual looping.
Example: mapfile / readarray Basics
#!/bin/bash
data=$'apple\nbanana\ncherry'
mapfile -t fruits <<< "$data"
echo "Element count: ${#fruits[@]}"
echo "Second fruit: ${fruits[1]}"
Login to try C/C++/Java/PHP code in the editor
readarray Is the Same as mapfile
readarray is exactly the same builtin as mapfile, just under an alternate name -- the two are fully interchangeable in every script. Some scripts use one name for stylistic reasons, but there is no functional difference.
Example: readarray Is the Same as mapfile
#!/bin/bash
printf "line one\nline two\nline three\n" > lines.txt
readarray -t lines < lines.txt
for line in "${lines[@]}"; do
echo "Read: $line"
done
Login to try C/C++/Java/PHP code in the editor
Why -t Matters
Without the -t flag, mapfile/readarray keeps the trailing newline character attached to the end of every captured element, which can cause subtle bugs when comparing or displaying those values later. Using -t strips it, giving clean line content.
Example: Why -t Matters
#!/bin/bash
data=$'first\nsecond'
mapfile -t clean_lines <<< "$data"
mapfile raw_lines <<< "$data"
echo "Clean (with -t): [${clean_lines[0]}]"
echo "Raw (without -t): [${raw_lines[0]}]"
Login to try C/C++/Java/PHP code in the editor
read -a for Splitting a Single Line
read -a arr splits one line of input into array elements based on IFS (whitespace by default), which is different from mapfile's job of turning multiple lines into multiple elements. This is handy for parsing a single space-separated line of fields.
Example: read -a for Splitting a Single Line
#!/bin/bash
read -a fields <<< "red green blue"
echo "Number of fields: ${#fields[@]}"
echo "Second field: ${fields[1]}"
Login to try C/C++/Java/PHP code in the editor
- Using
arr=($(command))and assuming each line becomes one element; that form actually word-splits on all whitespace (not just newlines), so a line with multiple words gets broken into multiple array elements. - Forgetting
mapfile/readarray(they are the same command,readarrayis an alias) are Bash 4.0+ features and won't work on very old Bash or onsh. - Not using
-twithmapfile/readarray, which leaves the trailing newline character attached to the end of every captured element.
mapfile -t arr <<< "$data"(or< file) reads input line by line directly into an array, one element per line.readarrayis simply another name for the exact same builtin asmapfile-- they are fully interchangeable.- The
-tflag strips the trailing newline from each line before storing it as an element -- almost always what you want. read -a arr <<< "$line"splits a single line into an array by whitespace (usingIFS), which is a different use case from reading multiple lines.
Chapter Quiz — Complete all 10 topics to unlock
0/10 topics done
Complete these topics first: