Reputation: 23
Really need some help with this one, trying to use sed (hope this is the best solution) to replace last comma for each block of lat longs. examples below.
Original file
;REGION
SOLID,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG,
;REGION
SOLID,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG,
;REGION
SOLID,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG,
Resulting file
;REGION
SOLID,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG;
;REGION
SOLID,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG;
;REGION
SOLID,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG;
Upvotes: 2
Views: 244
Reputation: 58578
This might work for you (GNU sed):
sed '/^;/!{H;$!d};1{h;d};x;s/,$/;/' file
or looking at it another way:
sed '/,$/{H;$!d};1{h;d};x;s//;/' file
If the line doesn't begin with ;
(or does end with ,
) add it to the hold space (HS) and then delete it if it is not the last line. Otherwise it must begin ';' (or does not end in ,
) and if it's the first line add it to the HS and delete it else swap to the HS and subsititute the last ,
for ;
. N.B. the current line is now in the HS. For edge case of it being the last line, it is not deleted and falls through and is also acted on by subsititution command.
Upvotes: 1
Reputation: 36282
One solution that saves only each block between region
lines and substitutes last comma:
sed -n '
## If first line, print and process next one.
1 { p; b };
## While not match "region" line, save data to hold space and
## process next one. If last line avoid read next one because
## it would end the script.
/^;REGION/! { H; $! b };
## Get data of hold space.
x;
## Remove leading newline created with "H" instruction.
s/^\n//;
## Substitute last comma.
s/,$/;/;
## Print all.
p;
## Remove to save next block of data.
s/^.*$//
' infile
It yields:
;REGION
SOLID,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG;
;REGION
SOLID,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG;
;REGION
SOLID,
LAT,LONG,
LAT,LONG,
LAT,LONG,
LAT,LONG;
Upvotes: 2
Reputation: 9311
I'd use awk
:
/^;/ {if(last) print gensub(/,$/,";","",last);print; next;}
{if(last) print last; last=$0}
END {print gensub(/,$/,";","",last)}
Save this to a file like fix.awk
and run
awk -f fix.awk < data
Explanations:
/^;/ {...}
- execute {...}
code on all lines starting with ;
print gensub(/,$/,";","",last)
- replace the last ,
with ;
in the variable last
(which hold the previous line)
print;
- print the current line
next
- go to next line (and don't execute {if(last) print last; last=$0}
on this line)
Upvotes: 2
Reputation: 65861
A sed
solution:
sed -n 'N;/\n;/s/,\n/;\n/;P;$s/.*\n\(.*\),$/\1;/p;D' file
The ugliness is from the necessity to process the last line separately. Without it the command would be
sed -n 'N;/\n;/s/,\n/;\n/;P;D' file
Upvotes: 2
Reputation: 195269
try this awk line:
awk '!/LONG,$/{if(p~/LONG,/)sub(/,$/,";",p)}
{if(p)print p;p=$0}
END{if(p~/LONG,/)sub(/,$/,";",p);print p}' file
Upvotes: 1