0

I have a issue in processing data of below variable to the dynamic array

variable_1='A|B|C|D' -> dynamic_array=(A B C D)

I tried using sed command to replace '|' with space and how do I pass data to dynamic_array

Is their any way to achieve within one line of code?

3

3 Answers 3

3

Without changing IFS, since Bash 4.4:

readarray -td '|' arr < <(printf '%s' "$var")
$ var='A|B|C|D'
$ readarray -td '|' arr < <(printf '%s' "$var")
$ echo "${arr[0]}"; echo "${arr[3]}"
A
D

See help readarray for explanation.

Note: My previous suggestion (readarray -td '|' arr <<< "$var"), although briefer, would insert a spurious newline at the last array element, as Freddy pointed.

1
  • 1
    Note that it turns both var='A|B' and var='A|B|' into arr=(A B), though it turns var='' into arr=() and var='|' into arr=(''). Nov 12, 2020 at 10:25
2

Assuming bash:


You can make use of word splitting. Internal Field Separator (IFS) defaults to space, tab or newline. But you can override it with setting the IFS environment variable, then you can use the normal ways to create a variable:

set -f # disable filename expansion
IFS='|' arr=($variable_1)

or declare:

IFS='|' declare -a 'arr=($variable_1)'

or read:

IFS='|' read -ra arr  <<<  "$variable_1"

If you change the IFS variable like this, you may want to save it first in another variable and reset it afterwards:

OLD_IFS="$IFS"
# my commands
IFS="$OLD_IFS"
6
  • can you explain a little bit Nov 11, 2020 at 10:48
  • 3
    You should mention that after the first, IFS will stay set to |, potentially breaking other commands. IFS='|' arr=($var) does NOT work like IFS= read .. -- IFS does not revert to its old value after that.
    – user414777
    Nov 11, 2020 at 11:53
  • read -ra is the best answer, but I would strongly encourage you to be more vigilant about quoting your variables. The first one in particular is not recommended unless you also do set -f Nov 11, 2020 at 14:29
  • thanks, updated my answer to reflect your comments. Very much appreciated.
    – pLumo
    Nov 12, 2020 at 6:56
  • @glennjackman, read -ra only works for data that doesn't contain newline characters. It also removes trailing empty elements. For that you need: set -o noglob; IFS='|'; array=($string"") Nov 12, 2020 at 9:44
0

Assuming zsh, you can use the s parameter expansion flag which will work whatever characters or non-characters the elements contain:

$ string=$'first element|second\nbinary\x80element\0||second-last|'
$ array=("${(@s[|])string}")
$ typeset -p string array
typeset string=$'first element|second\nbinary\M-\C-@element\C-@||second-last|'
typeset -a array=( 'first element' $'second\nbinary\M-\C-@element\C-@' '' second-last '' )

Note that the empty string is split into one empty element (string='' gives array=( '' ), not array=( )).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.