Turning multi-line string into single comma-separated

StringBashShellCsv

String Problem Overview


Let's say I have the following string:

something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

How do I turn that into simply

+12.0,+15.5,+9.0,+13.5

in bash?

String Solutions


Solution 1 - String

Clean and simple:

awk '{print $2}' file.txt | paste -s -d, -

Solution 2 - String

You can use awk and sed:

awk -vORS=, '{ print $2 }' file.txt | sed 's/,$/\n/'

Or if you want to use a pipe:

echo "data" | awk -vORS=, '{ print $2 }' | sed 's/,$/\n/'

To break it down:

  • awk is great at handling data broken down into fields
  • -vORS=, sets the "output record separator" to ,, which is what you wanted
  • { print $2 } tells awk to print the second field for every record (line)
  • file.txt is your filename
  • sed just gets rid of the trailing , and turns it into a newline (if you want no newline, you can do s/,$//)

Solution 3 - String

cat data.txt | xargs | sed -e 's/ /, /g'

Solution 4 - String

This might work for you:

cut -d' ' -f5 file | paste -d',' -s
+12.0,+15.5,+9.0,+13.5

or

sed '/^.*\(+[^ ]*\).*/{s//\1/;H};${x;s/\n/,/g;s/.//p};d' file
+12.0,+15.5,+9.0,+13.5

or

sed 's/\S\+\s\+//;s/\s.*//;H;$!d;x;s/.//;s/\n/,/g' file

For each line in the file; chop off the first field and spaces following, chop off the remainder of the line following the second field and append to the hold space. Delete all lines except the last where we swap to the hold space and after deleting the introduced newline at the start, convert all newlines to ,'s.

N.B. Could be written:

sed 's/\S\+\s\+//;s/\s.*//;1h;1!H;$!d;x;s/\n/,/g' file

Solution 5 - String

$ awk -v ORS=, '{print $2}' data.txt | sed 's/,$//'
+12.0,+15.5,+9.0,+13.5

$ cat data.txt | tr -s ' ' | cut -d ' ' -f 2 | tr '\n' ',' | sed 's/,$//'
+12.0,+15.5,+9.0,+13.5

Solution 6 - String

awk one liner

$ awk '{printf (NR>1?",":"") $2}' file

+12.0,+15.5,+9.0,+13.5

Solution 7 - String

This should work too

awk '{print $2}' file | sed ':a;{N;s/\n/,/};ba'

Solution 8 - String

You can use grep:

grep -o "+\S\+" in.txt | tr '\n' ','

which finds the string starting with +, followed by any string \S\+, then convert new line characters into commas. This should be pretty quick for large files.

Solution 9 - String

Try this easy code:

awk '{printf("%s,",$2)}' File1

Solution 10 - String

try this:

sedSelectNumbers='s".* \(+[0-9]*[.][0-9]*\) .*"\1,"'
sedClearLastComma='s"\(.*\),$"\1"'
cat file.txt |sed "$sedSelectNumbers" |tr -d "\n" |sed "$sedClearLastComma"

the good thing is the easy part of deleting newline "\n" characters!

EDIT: another great way to join lines into a single line with sed is this: |sed ':a;N;$!ba;s/\n/ /g' got from here.

Solution 11 - String

A solution written in pure Bash:

#!/bin/bash

sometext="something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)"

a=()
while read -r a1 a2 a3; do
	# we can add some code here to check valid values or modify them
	a+=("${a2}")
done <<< "${sometext}"
# between parenthesis to modify IFS for the current statement only
(IFS=',' ; printf '%s: %s\n' "Result" "${a[*]}")

Result: +12.0,+15.5,+9.0,+13.5

Solution 12 - String

Don't seen this simple solution with awk

awk 'b{b=b","}{b=b$2}END{print b}' infile

Solution 13 - String

With perl:

fg@erwin ~ $ perl -ne 'push @l, (split(/\s+/))[1]; END { print join(",", @l) . "\n" }' <<EOF
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)
EOF

+12.0,+15.5,+9.0,+13.5

Solution 14 - String

You can also do it with two sed calls:

$ cat file.txt 
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)
$ sed 's/^[^:]*: *\([+0-9.]\+\) .*/\1/' file.txt | sed -e :a -e '$!N; s/\n/,/; ta'
+12.0,+15.5,+9.0,+13.5

First sed call removes uninteresting data, and the second join all lines.

Solution 15 - String

You can also print like this:

Just awk: using printf

bash-3.2$ cat sample.log
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

bash-3.2$ awk ' { if($2 != "") { if(NR==1) { printf $2 } else { printf "," $2 } } }' sample.log
+12.0,+15.5,+9.0,+13.5

Solution 16 - String

Another Perl solution, similar to Dan Fego's awk:

perl -ane 'print "$F[1],"' file.txt | sed 's/,$/\n/'

-a tells perl to split the input line into the @F array, which is indexed starting at 0.

Solution 17 - String

Well the hardest part probably is selecting the second "column" since I wouldn't know of an easy way to treat multiple spaces as one. For the rest it's easy. Use bash substitutions.

# cat bla.txt
something1:    +12.0   (some unnecessary trailing data (this must go))
something2:    +15.5   (some more unnecessary trailing data)
something4:    +9.0   (some other unnecessary data)
something1:    +13.5  (blah blah blah)

# cat bla.sh
OLDIFS=$IFS
IFS=$'\n'
for i in $(cat bla.txt); do
  i=$(echo "$i" | awk '{print $2}')
  u="${u:+$u, }$i"
done
IFS=$OLDIFS
echo "$u"

# bash ./bla.sh
+12.0, +15.5, +9.0, +13.5

Solution 18 - String

Yet another AWK solution

Run

awk '{printf "%s", $c; while(getline){printf "%s%s", sep, $c}}' c=2 sep=','

to use the 2nd column to form the list separated by commas. Give the input as usual in standard input or as a file name argument.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlex CoplanView Question on Stackoverflow
Solution 1 - StringMattias AhnbergView Answer on Stackoverflow
Solution 2 - StringDan FegoView Answer on Stackoverflow
Solution 3 - StringBhargav SrinivasanView Answer on Stackoverflow
Solution 4 - StringpotongView Answer on Stackoverflow
Solution 5 - StringkevView Answer on Stackoverflow
Solution 6 - StringRahul VermaView Answer on Stackoverflow
Solution 7 - Stringjaypal singhView Answer on Stackoverflow
Solution 8 - StringkenorbView Answer on Stackoverflow
Solution 9 - StringVontonView Answer on Stackoverflow
Solution 10 - StringAquarius PowerView Answer on Stackoverflow
Solution 11 - StringQuatro por QuatroView Answer on Stackoverflow
Solution 12 - Stringctac_View Answer on Stackoverflow
Solution 13 - StringfgeView Answer on Stackoverflow
Solution 14 - StringElias DornelesView Answer on Stackoverflow
Solution 15 - Stringuser982733View Answer on Stackoverflow
Solution 16 - StringChris KoknatView Answer on Stackoverflow
Solution 17 - StringMarkiView Answer on Stackoverflow
Solution 18 - StringjarnoView Answer on Stackoverflow