How can I convert a string to an array of single characters in Bash?
How to take a string, something as simple as "Hello World!" and split it into individual characters?
Using the example above, I want an array with one character to fit in each value. Thus, the internal elements of the array look like this:
{"H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d", "!"}
source to share
str="Hello world!"
for (( i=0 ; i < ${#str} ; i++ )) {
arr[$i]=${str:i:1}
}
#print
printf "=%s=\n" "${arr[@]}"
Output
=H= =e= =l= =l= =o= = = =w= =o= =r= =l= =d= =!=
You can assign the result of any command to an array with
mapfile -t array < <(command args)
Unfortunately, -d
bash 4.4. + Is required to define a custom delimiter . Let's say you need to split this line into 2 char pieces - using grep
mapfile -t -d '' a2 < <(grep -zo .. <<<"$str")
printf "=%s=\n" "${a2[@]}"
output:
=He= =ll= =o = =wo= =rl= =d!=
source to share
A clean Bash approach is to loop through the string one character at a time and take the substring:
#!/bin/bash
declare -a arr
string="Hello World!"
for ((i = 0; i < ${#string}; i++)); do
# append i'th character to the array as a new element
# double quotes around the substring make sure whitespace characters are protected
arr+=("${string:i:1}")
done
declare -p arr
# output: declare -a arr=([0]="xy" [1]="y" [2]="H" [3]="e" [4]="l" [5]="l" [6]="o" [7]="W" [8]="o" [9]="r" [10]="l" [11]="d" [12]="!")
source to share
I see two ways to do this. In pure Bash, iterating over a character in a string by character and adding each character to an array:
$ str='Hello World!'
# for (( i = 0; i < ${#str}; ++i )); do myarr+=("${str:i:1}"); done
$ declare -p myarr
declare -a myarr='([0]="H" [1]="e" [2]="l" [3]="l" [4]="o" [5]=" " [6]="W" [7]="o" [8]="r" [9]="l" [10]="d" [11]="!")'
The key element is substring expansion "${str:i:1}"
, which expands to a substring str
that starts with an index i
and has a length of 1. Note that this is one of the few cases where you don't need to add a variable with $
to get its contents, because it i
's here in arithmetic context.
Using an external tool fold
:
$ readarray -t arr <<< "$(fold -w 1 <<< "$str")"
$ declare -p arr
declare -a arr='([0]="H" [1]="e" [2]="l" [3]="l" [4]="o" [5]=" " [6]="W" [7]="o" [8]="r" [9]="l" [10]="d" [11]="!")'
fold -w 1
wraps the input string with one character per line, and the command readarray
reads its input into an array, line by line ( -t
removes newlines from each element).
Please note that readarray
requires Bash 4.0 or newer.
source to share
This is a fairly simple task bash
using array indexing. Just flip all characters and select then into an array, eg.
#!/bin/bash
a="Hello World!"
for ((i = 0; i < ${#a}; i++)); do
array+=("${a:i:1}") ## use array indexing for individual chars
done
printf "%s\n" "${array[@]}" ## output individual chars
Usage / output example
$ sh bashchar.sh
H
e
l
l
o
W
o
r
l
d
!
source to share
For a change, the solution in pure Bash, without array indexing:
string="Hello world"
split=( )
while read -N 1; do
split+=( "$REPLY" )
done < <( printf '%s' "$string" )
The last line handles the substitution to feed the output printf
to the loop. The loop uses read -N 1
exactly one character to read at a time.
source to share