Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting a Bash array into a delimited string

I would like to know the following;

  1. Why the given non-working example doesn't work.
  2. If there are any other cleaner methods than those given in working example.

Non-working example

> ids=(1 2 3 4);echo ${ids[*]// /|} 1 2 3 4 > ids=(1 2 3 4);echo ${${ids[*]}// /|} -bash: ${${ids[*]}// /|}: bad substitution > ids=(1 2 3 4);echo ${"${ids[*]}"// /|} -bash: ${"${ids[*]}"// /|}: bad substitution 

Working example

> ids=(1 2 3 4);id="${ids[@]}";echo ${id// /|} 1|2|3|4 > ids=(1 2 3 4); lst=$( IFS='|'; echo "${ids[*]}" ); echo $lst 1|2|3|4 

In context, the delimited string to be used in a sed command for further parsing.

like image 793
koola Avatar asked Nov 20 '12 09:11

koola


People also ask

How do I echo an array in bash?

How to Echo a Bash Array? To echo an array, use the format echo ${Array[0]}. Array is your array name, and 0 is the index or the key if you are echoing an associative array. You can also use @ or * symbols instead of an index to print the entire array.

How do I create an array of strings in bash?

Using the tr Command to Split a String Into an Array in Bash It can be used to remove repeated characters, convert lowercase to uppercase, and replace characters. In the bash script below, the echo command pipes the string variable, $addrs , to the tr command, which splits the string variable on a delimiter, ; .

How do I modify an array in bash?

To update element of an array in Bash, access the element using array variable and index, and assign a new value to this element using assignment operator.


2 Answers

Because parentheses are used to delimit an array, not a string:

ids="1 2 3 4";echo ${ids// /|} 1|2|3|4 

Some samples: Populating $ids with two strings: a b and c d

ids=("a b" "c d")  echo ${ids[*]// /|} a|b c|d  IFS='|';echo "${ids[*]}";IFS=$' \t\n' a b|c d 

... and finally:

IFS='|';echo "${ids[*]// /|}";IFS=$' \t\n' a|b|c|d 

Where array is assembled, separated by 1st char of $IFS, but with space replaced by | in each element of array.

When you do:

id="${ids[@]}" 

you transfer the string build from the merging of the array ids by a space to a new variable of type string.

Note: when "${ids[@]}" give a space-separated string, "${ids[*]}" (with a star * instead of the at sign @) will render a string separated by the first character of $IFS.

what man bash says:

man -Len -Pcol\ -b bash | sed -ne '/^ *IFS /{N;N;p;q}'    IFS    The  Internal  Field  Separator  that  is used for word splitting           after expansion and to split  lines  into  words  with  the  read           builtin command.  The default value is ``<space><tab><newline>''. 

Playing with $IFS:

declare -p IFS declare -- IFS="  " printf "%q\n" "$IFS" $' \t\n' 

Literally a space, a tabulation and (meaning or) a line-feed. So, while the first character is a space. the use of * will do the same as @.

But:

{     IFS=: read -a array < <(echo root:x:0:0:root:/root:/bin/bash)          echo 1 "${array[@]}"     echo 2 "${array[*]}"     OIFS="$IFS" IFS=:     echo 3 "${array[@]}"     echo 4 "${array[*]}"     IFS="$OIFS" } 1 root x 0 0 root /root /bin/bash 2 root x 0 0 root /root /bin/bash 3 root x 0 0 root /root /bin/bash 4 root:x:0:0:root:/root:/bin/bash 

Note: The line IFS=: read -a array < <(...) will use : as separator, without setting $IFS permanently. This is because output line #2 present spaces as separators.

like image 57
F. Hauri Avatar answered Oct 05 '22 07:10

F. Hauri


You can use printf too, without any external commands or the need to manipulate IFS:

ids=(1 2 3 4)                     # create array printf -v ids_d '|%s' "${ids[@]}" # yields "|1|2|3|4" ids_d=${ids_d:1}                  # remove the leading '|' 
like image 43
codeforester Avatar answered Oct 05 '22 07:10

codeforester