1

I'm trying to split key value pairs (around an = sign) which I then use to edit a config file, using bash. But I need an alternative to the <<< syntax for IFS.

The below works on my host system, but when i log in to my ubuntu virtual machine through ssh I have the wrong bash version. Whatever I try, <<< fails. (I am definitely calling the right version of bash at the top of the file, using #!/bin/bash (and I've tried #!/bin/sh etc too)).

I know I can use IFS as follows on my host mac os x system:

var="word=hello"        
IFS='=' read -a array <<<"$var"
echo ${array[0]} ${array[1]]}

#alternative -for calling through e.g. sh file.sh param=value
for var in "$@"
    do      
    IFS='=' read -a array <<<"$var"
    echo ${array[0]} ${array[1]]}
done


#alternative
  IFS='=' read -ra array <<< "a=b"
  declare -p array
  echo ${array[0]} ${array[1]}

But this doesn't work on my vm.

I also know that I can should be able to switch the <<< syntax through backticks, $() or echo "$var" | ... but I can't get it to work - as follows:

#Fails
    IFS='=' read -ra myarray -d '' <"$var"
    echo ${array[0]} ${array[1]]}

#Fails
    echo "$var" | IFS='=' read -a array
    echo ${array[0]} ${array[1]]}

#fails
echo "a=b" | IFS='=' read -a array
declare -p array
echo ${array[0]} ${array[1]}

Grateful for any pointers as I'm really new to bash.

Trevor Boyd Smith
  • 18,164
  • 32
  • 127
  • 177
Simeon
  • 848
  • 1
  • 11
  • 34

2 Answers2

3

Your first failed attempt is because < and <<< are different operators. < opens the named file.

The second fails because read only sets the value of array in the subshell started by the pipe; that shell exits after the completion of the pipe, and array disappears with it.

The third fails for the same reason as the second; the declare that follows doesn't make any difference.

chepner
  • 497,756
  • 71
  • 530
  • 681
2

Your attempts have been confounded because you have to use the variable in the same sub-shell as read.

$ echo 'foo=bar' | { IFS='=' read -a array; echo ${array[0]}; }
foo

And if you want your variable durable (ie, outside the sub-shell scope):

$ var=$(echo 'foo=bar' | { IFS='=' read -a array; echo ${array[0]}; })
$ echo $var
foo

Clearly, it isn't pretty.


Update: If -a is missing, that suggests you're out of the land of arrays. You can try parameter substitution:

str='foo=bar'
var=${str%=*}
val=${str#*=}

And if that doesn't work, fall back to good ole cut:

str='foo=bar'
var=$(echo $str | cut -f 1 -d =)
val=$(echo $str | cut -f 2 -d =)
bishop
  • 37,830
  • 11
  • 104
  • 139