sahil
sahil

Reputation: 135

Converting a list of strings into a single line with sed/awk on linux

I have a file say test.txt, which contains data as a list of values/strings and also has some empty lines in between as shown below

Val1  
Val2  
Val3

Val4  
Val5         
         
     
    
Val6

Required output:

Val1, Val2, Val3  
Val4, Val5  
Val6

I am using the below command, but it's returning all the available values in a single line. But I want only consecutive values to be concatenated together(comma separated) and a new line should start whenever it hits an empty line (there can be more than one consecutive empty line).

cat test.txt | sed 's/<[^>]*>//g' | sed 's/ //g' | sed 's/.*/&/;$!s/$/, /' | tr -d '\n'

Upvotes: 9

Views: 709

Answers (6)

Franz Kafka
Franz Kafka

Reputation: 21

Try this one:

awk '{if(NF){if(line!="")line=line", "$0;else line=$0;}else{if(line!=""){print line;line=""} } } END{if(line) print line}' test.txt

Output:

Val1, Val2, Val3
Val4, Val5
Val6

Upvotes: 2

Jetchisel
Jetchisel

Reputation: 7791

If GNU/BSD ed is available/acceptable.

ed -s file.txt <<-'EOF'
  ,$-1g/.\{1,\}/;/^$/-1s/$/, /
  ,$-1g/.\{1,\}/;/^$/j
  g/^$/d
  %s/, *$//
  %p
  Q
EOF

In one line, something like:

printf '%b\n' ',$-1g/.\{1,\}/;/^$/-1s/$/, /' ',$-1g/.\{1,\}/;/^$/j' 'g/^$/d' '%s/, *$//' %p Q | ed -s file.txt

Upvotes: 2

RavinderSingh13
RavinderSingh13

Reputation: 133458

1st solution: With your shown samples only, please try following GNU awk code.

awk -v RS=  'RT{gsub(/\n/,", ");print}'  Input_file


2nd solution: With GNU awk and with your shown samples please try following awk code.

awk -v RS='([^\n]*\n)+' '
RT && num=split(RT,arr,"\n\n"){
  val=""
  for(i=1;i<=num;i++){
     sub(/,$/,"",arr[i])
     gsub(/\n+/,", ",arr[i])
     print arr[i]
  }
}
'  Input_file

Upvotes: 4

potong
potong

Reputation: 58371

This might work for you (GNU sed):

sed ':a;N;s/\n$//;t;s/\n/, /;ta' file

Append the following line and if that line is empty, remove and print the result.

Otherwise, replace the newline by , and repeat.

Upvotes: 2

Ed Morton
Ed Morton

Reputation: 203254

I think this is what you're trying to do, using any awk:

$ awk -v RS= -F'\n' -v OFS=', ' '{$1=$1} 1' test.txt
Val1, Val2, Val3
Val4, Val5
Val6

Upvotes: 10

The fourth bird
The fourth bird

Reputation: 163217

With gnu-sed you can read the whole file with -z

Capture 2 non newlines in 2 capture groups surrounding a single newline, and in the replacement use 2 backreferences with , in between

Then replace 2 or more newlines with a single newline.

sed -Ez 's/([^\n])\n([^\n])/\1, \2/g;s/\n{2,}/\n/g' file

Output

Val1, Val2, Val3
Val4, Val5
Val6

Using only sed -E you can accomplish the same using a label reading all lines:

sed -E ':a;$!{N;ba};s/([^\n])\n([^\n])/\1, \2/g;s/\n{2,}/\n/g' file

Upvotes: 3

Related Questions