help-bash
[Top][All Lists]
Advanced

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

Re: split a string into an array?


From: Kerin Millar
Subject: Re: split a string into an array?
Date: Fri, 11 Mar 2022 05:32:56 +0000

On Fri, 11 Mar 2022 14:02:40 +0900
Koichi Murase <myoga.murase@gmail.com> wrote:

> 2022年3月11日(金) 13:07 Kerin Millar <kfm@plushkava.net>:
> > You could do it this way instead:
> >
> > $ readarray -t -d $'\t' array < <(printf %s $'a\t\tb\tc')
> > $ declare -p array
> > declare -a array=([0]="a" [1]="" [2]="b" [3]="c")
> > $ readarray -t -d $'\t' array < <(printf '')
> > $ declare -p array
> > declare -a array=()
> 
> There is still another corner case. The last empty element will be lost.
> 
> $ readarray -t -d $'\t' array < <(printf %s $'a\t')
> $ declare -p array
> declare -a array=([0]="a")
> 
> This can be solved by appending an extra separator in the input.
> 
> $ sep=$'\t' input=$'a\t'
> $ mapfile -t -d "$sep" array < <(printf %s "$input${input:+$sep}")

Right. Well spotted.

> 
> --
> 
> I guess Peng is interested in a solution without forks. If so, we may
> use the original code by Peng but with an additional check for the
> empty input.
> 
> The original code still involves pipes (or temporary files in older
> Bash or for a large input) by here strings. Instead, I usually do
> something like
> 
> if [[ -o noglob ]]; then
>   IFS=$sep builtin eval 'array=($input${input:+sep})'
> else
>   set -f
>   IFS=$sep builtin eval 'array=($input${input:+sep})'
>   set +f
> fi
> 
> Note: "noglob / set -f" is needed to suppress unwanted pathname
> expansions. "eval" is used to make IFS local to this command.
> "builtin" is needed to make sure that the tempenv IFS doesn't remain
> in the POSIX mode.

The problem with this is that the same word splitting behavioural issues that 
would also apply to read then come into play. For instance:

$ set -f
$ sep=$'\t' input=$'foo\t\t\tbar\t'
$ IFS=$sep builtin eval 'array=($input${input:+$sep})'
$ declare -p array
declare -a array=([0]="foo" [1]="bar")

-- 
Kerin Millar



reply via email to

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