Reputation: 135
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
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
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
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
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
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
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