3

How do I take a string, something simple like "Hello World!" and split it into its individual characters?

Using the example above, I want an array with a single character put into each value. So the array's internals would end up looking like:

{"H", "e", "l", "l", "o", " ", "W", "o", "r", "l", "d", "!"}

1
  • awk -v FS="" ' {printf"{";for(i=1;i<=NF;i++) if(i!=NF)printf "\""$i"\",";print $i"}"}' inputfile this has flaws so not putting it as answer. Commented Apr 12, 2017 at 5:47

8 Answers 8

4
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 into array the result of any command using the

mapfile -t array < <(command args)

Unfortunately, defining the custom delimiter -d needs bash 4.4.+. Let say, want break the above string into 2 char pieces - using grep

mapfile -t -d ''  a2 < <(grep -zo .. <<<"$str")
printf "=%s=\n" "${a2[@]}"

output:

=He=
=ll=
=o =
=wo=
=rl=
=d!=
Sign up to request clarification or add additional context in comments.

Comments

1

It is a fairly simple thing to do in bash using array indexing. Simply loop over all chars and pick then off into an array, e.g.

#!/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

Example Use/Output

$ sh bashchar.sh
H
e
l
l
o

W
o
r
l
d
!

4 Comments

You didn't quote "${array[@]}", which swallowed the space ;)
Good catch :)
I meant in the last line, ${array[@]} unquoted gets split up and the space disappears.
UUgh, never try and make correction on intuition :)
1

I can see two ways to do that. In pure Bash, iterating over the string character 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 the substring expansion, "${str:i:1}", which expands to the substring of str that starts at index i and has length 1. Notice that this is one of the few times where you don't have to prepend a variable with $ to get its contents, because the i is in an arithmetic context here.

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 to one character per line, and the readarray command read its input into an array, line by line (-t removes the newline characters from each element).

Notice that readarray requires Bash 4.0 or newer.

Comments

1

Pure Bash approach - walk through the string one character at a time and grab 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]="!")

Comments

0

Try this -

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

Comments

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

Comments

0

If you are trying to generate JSON, use square instead of curly brackets and jq instead of Bash:

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

Comments

0

For the sake of variety, a 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 does process substitution to pass the output of printf to a loop. The loop uses read -N 1 to read exactly one character at a time.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.