help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

String to array


From: Tapani Tarvainen
Subject: String to array
Date: Thu, 30 Sep 2021 15:52:16 +0300

Is there some simple way to convert a string into an array in bash,
with each character as an array element?

It can obviously be done with a loop, e.g.,

array=()
while [ -n "$string" ]
do
   array+=("${string:0:1}")
   string=${string:1}
done

or, preserving the original string,

array=()
i=0
while (( i < ${#string} ))
do
   array+=("${string:$((i++)):1}")
done

and of course those are good enough for all(?) practical purposes, but
I started wondering if there's a way to do it without an explicit
loop. So this is not a practical problem, but perhaps someone will
find it an amusing exercise.

Here's my first idea:

array=($(sed 's/./& /g' <<<$string))

That sort of works, but it forks an extra process (sed) and loses
whitespace and breaks in interesting ways with any number of special
characters like *.

This fixes most of those problems:

fopt=${-//[!f]}
set -f
OLDIFS=$IFS
IFS=$'\n'
array=($(sed 's/./&\n/g' <<<$string))
IFS=$OLDIFS
set ${fopt:+-}${fopt:-+f}

but it still loses newlines in the string and is harder to understand
and indeed even longer than the loops above - and it still calls sed,
and I'd like to do this with shell builtins only.

(Side question: is there a better way to restore set -f/+f?)

Playing a little with brace expansion I came up with this:

eval tmparray=('\"\${string:'{0..$((${#string}-1))}':1}\"')
eval array=(${tmparray[@]})

That works, but... let's just say it might be useful in some code
confuscation contest, hardly otherwise.

But I can't shake the feeling that there should be some simple and
pretty way to do it with some such construct. Or at least something
simpler than that double eval thing. Especially since the reverse
operation is so simple:

OLDIFS=$IFS
IFS=
string=${array[*]}
IFS=$OLDIFS

Ideas?

-- 
Tapani Tarvainen



reply via email to

[Prev in Thread] Current Thread [Next in Thread]