4

I am trying to convert string variable to an array with following code.

#/bin/sh
VERSION='1.2.3'
echo $VERSION
IFS='.' read -a array <<< "$VERSION"
echo ${#array[@]}
echo ${array[@]}

But getting following error when I run sh test.sh

1.2.3
test.sh: 4: test.sh: Syntax error: redirection unexpected

Version :

ubuntu@jenkins-slave1:~$ $SHELL --version
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later         
<http://gnu.org/licenses/gpl.html>

OS :

ubuntu@jenkins-slave1:~$ cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.1 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.1 LTS"
  • Also FWIW $SHELL is your user shell not necessarily /bin/sh, on ubuntu your /bin/sh is most likely dash – jesse_b Feb 24 at 20:08
5

<<< is a zsh operator now supported by a few other shells (including bash).

read -a is bash-specific. ksh had read -A for that long before bash (consistent with set -A; set -a being something else inherited from the Bourne shell; also supported by zsh and yash)

sh these days is an implementation or another of an interpreter for the POSIX sh language. That language has neither <<< nor read -a nor arrays (other than "$@").

On Ubuntu, by default, the shell used as sh interpreter is dash which is very close to the POSIX sh specification in that it implements very few extensions over what POSIX specifies. It implements none of <<<, read -a nor arrays.

In POSIX sh, to split a string into the one POSIX sh array ("$@"), you'd use:

IFS=.             # split on .
set -o noglob     # disable glob
set -- $VERSION"" # split+glob with glob disabled.
echo "$# elements:"
printf ' - "%s"\n' "$@"

It has a few advantages over the bash-specific IFS=. read -a <<< $string syntax:

  • it doesn't need creating a temporary file and storing the contents of $string in it.
  • it works even if $string contains newline characters (read -a <<< $string) would only read the first line.
  • it works even if $string contains backslash characters (with read, you need the -r option for backslash not to undergo a special processing).
  • it's standard.
  • it works for values like 1.2.. read -a <<< $string would split it into "1" and "2" only instead of "1", "2" and "".
  • in older versions of bash, you had to quote the $string (IFS=. read -ra <<< "$string") or otherwise it would undergo splitting (followed by joining with space).
|improve this answer|||||
  • Is it possible to create an array variable ? – roy Feb 24 at 20:11
  • 1
    @roy, as I said, sh has no array variables (other than "$@" which is not really a variable). shells with array variable support include (t)csh, ksh, rc, bash, zsh, es, akanga, fish, yash. Pick one. In that list, I'd recommend zsh or rc. – Stéphane Chazelas Feb 24 at 20:14
3

You're hashbang is /bin/sh and you are running the script with sh, which does not support the <<< herestring. If you use /bin/bash it will work.

Additionally, while /bin/sh often supports arrays it is not required to do so, if an array is required you should use ksh, bash, zsh, or another shell that has support for them.

|improve this answer|||||

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.