Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I convert an array into a comma separated string?

Tags:

arrays

bash

shell

I have an array and I am printing it like this:

echo "${data[*]}"

Output:

/QE-CI-RUN-71/workspace/QE-AU/57/testng-results_1.xml 
/QE-CI-RUN-71/workspace/QE-AU/57/testng-results_2.xml

I want to store the above output as a comma separated value. How can I achieve this in Bash?

The data array is dynamic, it may have any number of values.

like image 358
ArrchanaMohan Avatar asked Dec 18 '18 18:12

ArrchanaMohan


People also ask

How do you convert an array to a comma-separated string in Python?

Use the join() Function to Convert a List to a Comma-Separated String in Python. The join() function combines the elements of an iterable and returns a string. We need to specify the character that will be used as the separator for the elements in the string.

How do I convert an array of numbers to strings?

To convert an array of numbers to an array of strings, call the map() method on the array, and on each iteration, convert the number to a string. The map method will return a new array containing only strings.

How do you add comma-separated values in an array in Java?

All you need to do is first split the given String on delimiter e.g. comma using the split() method, this will give you an array of String. Now, you can pass that array to Arrays. asList() method to create a list, but remember this would be a fixed-length list and not truly an ArrayList.

How to convert array to comma separated string in JavaScript?

The join () method creates and returns a new string by concatenating all of the elements in an array. Note: The elements of the array will be separated by a specified separator. If not specified, Default separator comma (, ) is used. Let’s take various examples for convert array to a comma separated string javascript with different technics.

How do you split a comma out of a string?

The split () method is used to split a string into an array of substrings, and returns the new array. Pass your comma-separated string into this function and it will return an array, and if a comma-separated string is not found then it will return null.

How to convert array to delimited string in JavaScript?

Before convert array to delimited string in javascript, we would like to demonstrate to you two important methods of javascript. These methods will help convert array to string comma separated string. They are join () and toString () methods in js. Or if you want to convert strings to arrays in javascript.

How to convert an array to a string in JavaScript?

This is an inbuilt javascript method, which is used to converts an array into a String and returns the new string. The join () method creates and returns a new string by concatenating all of the elements in an array.


3 Answers

There are a few ways to do this:

1. Join directly with printf (via Charles Duffy’s comment)

printf -v joined '%s,' "${data[@]}"
echo "${joined%,}"

The printf builtin implicitly joins arrays. You could print interactively like 3a below with a one-liner reading printf '%s,' "${data[@]}", but you'd be left with a trailing comma. (This method even works in POSIX shell, though you'd have to use $@ as your array since POSIX can't handle other array types).

2. Change the $IFS field separator (via chepner’s answer)

join_arr() {
  local IFS="$1"
  shift
  echo "$*"
}

join_arr , "${data[@]}"

This redefines the field separator within just the scope of this function so when the $data array is automatically expanded, it uses the desired delimiter instead of the first value of the global $IFS or (if it's empty or undefined) space.

This could be done without a function, but there's some nastiness about preserving $IFS: Charles Duffy notes that reverting IFS="$OLD_IFS" after temporarily reassigning it could evaluate to IFS="", but if $IFS was previously undefined, that's different from unset IFS and while it's possible to tease those apart, this functional approach is far cleaner thanks to its use of local to limit $IFS’s scope.

This solution only supports single-character delimiters. See #5 below for a similar function that supports delimiters of any length.

3a. Loop through its contents (and print incrementally)

delim=""
for item in "${data[@]}"; do
  printf "%s" "$delim$item"
  delim=","
done
echo # add a newline

If other code in that loop involves an external call (or even sleep 0.1), you'll actually watch this build piece by piece, which can be helpful in an interactive setting.

3b. Loop through its contents (and build a variable)

delim=""
joined=""
for item in "${data[@]}"; do
  joined="$joined$delim$item"
  delim=","
done
echo "$joined"

4. Save the array as a string and run replacement on it (note, the array must lack spaces*)

data_string="${data[*]}"
echo "${data_string//${IFS:0:1}/,}"

* This will only work if the first character of $IFS (space by default) does not exist in any of the array's items.

This uses bash pattern substitution: ${parameter//pattern/string} will replace each instance of pattern in $parameter with string. In this case, string is ${IFS:0:1}, the substring of $IFS starting at the beginning and ending after one character.

Z Shell (zsh) can do this in one nested parameter expansion:

echo "${${data[@]}//${IFS:0:1}/,}"

(Though Z Shell can also do it more elegantly with its dedicated join flag as echo "${(j:,:)data}" as noted by @DavidBaynard in a comment below this answer.)

5. Join with replacement in an implicit loop (via Nicholas Sushkin's answer to a duplicate question)

join_by() {
  local d="${1-}" f="${2-}"
  if shift 2; then
    printf %s "$f" "${@/#/$d}"
  fi
}

join_by , "${data[@]}"

This is very similar to #2 above (via chepner), but it uses pattern substitution rather than $IFS and therefore supports multi-character delimiters. $d saves the delimiter and $f saves the first item in the array (I'll say why in a moment). The real magic is ${@/#/$d}, which replaces the beginning (#) of each array element with the delimiter ($d). As you don't want to start with a delimiter, this uses shift to get past not only the delimiter argument but also the first array element (saved as $f), which is then printed right in front of the replacement.

printf has an odd behavior when you give it extra arguments as we do here. The template (%s) only specifies that there will be one argument, so the rest of the arguments act as if it's a loop and they're all concatenated onto each other. Consider changing that key line to printf "%s\n" "$f" "${@/#/$d}". You'll end up with a newline after each element. If you want a trailing newline after printing the joined array, do it with printf %s "$f" "${@/#/$d}" $'\n' (we need to use the $'…' notation to tell bash to interpret the escape; another way to do this would be to insert a literal newline, but then the code looks weird).

like image 64
Adam Katz Avatar answered Oct 20 '22 10:10

Adam Katz


To make it easier to localize the change of IFS, use a function:

join () {
  local IFS="$1"
  shift
  echo "$*"
}

join , "${data[@]}"
like image 20
chepner Avatar answered Oct 20 '22 09:10

chepner


For ksh, try this!

foo=`echo $(echo ${data[@]}) | tr ' ' ','`

In this way you can control the delimiter by translating the space (default) to comma! (or any other you can think of) :)

like image 5
Dan Dimacuha Avatar answered Oct 20 '22 10:10

Dan Dimacuha