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", "!"}

+3


source to share


8 answers


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!=

      

+3


source


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]="!")

      

+1


source


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.

+1


source


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
!

      

+1


source


Try it -

$v="Hello World!"
$awk  '{n=split($0,a,""); for(i=1;i<=n;i++) {print a[i]}}' <<<"$v"
H
e
l
l
o

W
o
r
l
d
!

      

0


source


awk '{ for ( i=1;i<=length($0);i++ ) printf substr($0,i,1)"\n" }' <<< $str
mapfile arry1 < <(echo "$str1")

      

0


source


If you're trying to create JSON, use square instead of curly braces and jq

instead of Bash:

jq -c -R 'explode|map([.]|implode)' <<<'Hello World!'
["H","e","l","l","o"," ","W","o","r","l","d","!"]

      

0


source


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.

0


source







All Articles