help-bash
[Top][All Lists]
Advanced

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

Re: String to array


From: Greg Wooledge
Subject: Re: String to array
Date: Thu, 30 Sep 2021 09:48:13 -0400

On Thu, Sep 30, 2021 at 03:52:16PM +0300, Tapani Tarvainen wrote:
> Is there some simple way to convert a string into an array in bash,
> with each character as an array element?

A loop is the simple and obvious way.

> It can obviously be done with a loop, e.g.,
> [...]
> 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.

As I understand it, you're asking for "no explicit loops", and "no
forked processes".  That restricts the choices quite substantially.

Are implicit loops allowed?  I mean, they *must* be, right?  There's
no way to do this without a loop being involved in *some* underlying
layer, hidden away in the bowels of the shell.

Here's a thing:

unicorn:~$ string=$'hi bye\twhy\n\e[;1'
unicorn:~$ n=${#string}; eval "printf -v re '(.)%.0s' {1..$n}"
unicorn:~$ [[ $string =~ $re ]] && declare -p BASH_REMATCH
declare -a BASH_REMATCH=([0]=$'hi bye\twhy\n\E[;1' [1]="h" [2]="i" [3]=" " 
[4]="b" [5]="y" [6]="e" [7]=$'\t' [8]="w" [9]="h" [10]="y" [11]=$'\n' 
[12]=$'\E' [13]="[" [14]=";" [15]="1")

The implicit loops here are in the brace expansion, in the printf command,
and probably in the regular expression matcher that builds up the
BASH_REMATCH array variable.

You can use "${BASH_REMATCH[@]:1}" or similar to use the resulting list.

Here are some ways that *don't* work, or at least that I couldn't get
to work:

1) mapfile -d 'any character'

   There doesn't appear to be any way to let mapfile delimit the input
   by "any character in this set".  Its -d option only accepts one
   character as an argument (or one byte -- I'm not sure which).

2) mapfile -t -d $'\xff' array <<< 'expand string with \xff after each char'

   I couldn't find any sort of back-reference in ${parameter/pattern/string}
   to act as a substitute for sed $'s/./&\xff/g' .

3) [[ $string =~ (.)* ]]

   The (.) is only applied once, despite the closure * that follows it.
   (.)+ didn't work either.  That led to constructing the
   (.)(.)(.)... pattern instead.



reply via email to

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