2

I am looking to append each element of a bash array with | except the last one.

array=("element1" "element2" "element3")

My desired output would be

array=("element1"|"element2"|"element3")

What I have done

for i in ${!array[@]}; 
do
array1+=( "${array[$i]}|" )
done

Followed by

array=echo ${array1[@]}|sed 's/|$//'

Is there any other looping approach I can use that only appends the character until the last but one element?

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
Balajee Addanki
  • 690
  • 2
  • 9
  • 23

4 Answers4

2

You can use:

# append | all except last element
read -ra array < <( printf "%s|" "${array[@]:0:$((${#array[@]} - 1))}"; echo "${array[@]: -1}"; )

# Check array content now
declare -p array
declare -a array='([0]="element1|element2|element3")'
  • "${array[@]:0:$((${#array[@]} - 1))}" will get all but last element of array
  • "${array[@]: -1}" will get the last element of array
  • printf "%s|" will append | in front of all the arguments
  • < <(...) is process substitution to read output of any command from stdin
  • read -ra will read the input in an array
anubhava
  • 761,203
  • 64
  • 569
  • 643
2

For your special case, where only one single character has to be inserted between each array member, the simplest solution is probably to use array expansion (and changing the separation character IFS according to your need beforehand):

$ array=("element1" "element2" "element3")
$ array=( $( IFS="|" ; echo "${array[*]}") )
$ echo "\$array[0] is '${array[0]}'"
$array[0] is 'element1|element2|element3'
Alex O
  • 7,746
  • 2
  • 25
  • 38
  • This reduces the question to [this one](http://stackoverflow.com/questions/1527049/bash-join-elements-of-an-array), but OP seems to want an array with a single element - which is easily done, though, by using `array=($( IFS="|" ; echo "${array[*]}"))`. The command substitution neatly confines the `IFS` change to a subshell, so +1 :) – Benjamin W. Aug 18 '16 at 14:07
  • Yes, thanks for pointing this out. I didn't see the point to create a single-member array, but this is of course what has been asked for. I updated my response accordingly, so the output data type is "array" : ) – Alex O Aug 18 '16 at 14:36
1
$ array=("element1" "element2" "element3")
$ printf -v str "|%s" "${array[@]}"
$ array=("${str:1}")
$ declare -p array
declare -a array='([0]="element1|element2|element3")'

The printf statement creates a string str that contains |element1|element2|element3, i.e., one more | than we want (at the beginning).

The next statement uses substring parameter expansion, ${str:1}, to skip the first character and reassigns to array, which now consists of a single element.

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
1

A simple solution (if you don't mind changing IFS) is:

$ array=("element1" "element2" "element3")
$ IFS="|"; printf "%s\n" "${array[*]}"

And to re-assign to the variable array (which doesn't change IFS):

$ array=("$(IFS="|"; printf "%s\n" "${array[*]}")")
$ printf '%s\n' "${array[@]}"
element1|element2|element3

An alternative solution is:

$ array=($(printf '%s|' "${array[@]}")); array="${array%?}"
$ printf '%s\n' "${array}"

A more complex solution (script) is:

array=("element1" "element2" "element3")

       delimiter='|'
       unset newarr
for    val in "${array[@]}"
do     newarr=$newarr${newarr+"$delimiter"}$val
done

array=("$newarr")

echo "array=($array)"