help-bash
[Top][All Lists]
Advanced

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

Re: String to array


From: Alex fxmbsw7 Ratchev
Subject: Re: String to array
Date: Thu, 30 Sep 2021 15:10:54 +0200

you may get success accessing str via ${str:<position>:1}

s=ab34 i=-1 e=${#s} r= ; while (( n = ++i + 1 <= e )) ; do r+="pos $n char
${s:i:1}|" ; done ; printf %s\\n "${r%|}"

pos 1 char a|pos 1 char b|pos 1 char 3|pos 1 char 4

$n is a bug of 1 but you may get the point

a toarray id code a coproc awk to declare array, another mail with this may
follow

On Thu, Sep 30, 2021, 14:52 Tapani Tarvainen <bash@tapanitarvainen.fi>
wrote:

> 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]