Need a script to remove last comma in a file
I've written a sed script that does almost everything I want. The job that remains is to remove the last comma of a file. A typical file resembles this after sed is done with it:
Code:
enum MyEnum Can awk handle this job? It needs to be scripted in a language that are common in the Make environment, because it will have to be embedded in a makefile. Each enum gets its own file, btw. |
If the files are all short like that, you might just flip the text of the entire file with 'rev' and strip out the last comma before flipping it back.
|
Here's my offering, in perl.
Code:
#! /usr/bin/perl -w --- rod. |
Quote:
I'm figuring I'll be able to embed that into a makefile like this: Code:
define strip-last-comma |
Quote:
|
please ignore if I misunderstood your requirement
Code:
# sed 's|, *\/\/| \/\/|g' file |
Here's an awk program (since you asked):
Code:
$ cat test.awk Note: The code does not handle multiple brackets nor lines with both open and closing brackets. </edit> |
Quote:
Btw, here is a sed one-liner which replaces the final comma with a space (it makes some assumptions about the formatting: there will be a series of lines each containing one comma per line and the closing brace and semi-colon are on the line immediately following the line containing the final comma). So this will obviously have trouble if multi-line comments are dispersed through the enum. Code:
sed -e '/,/{x;/^$/d};/};/{H;x;s/,/ /}' file Code:
sed -e '/,/{x;/^$/d};/};/{H;s/.*//;x;s/,/ /}' file Code:
enum MyEnum |
Thanks for the alternate methods folks. It's great to have a few solutions to choose from. All this may turn out to be in vain, however.. I've discovered getting my original shell script ported into the Makefile is more complex than I had estimated (possible, but also tedious). Although I'll probably at least incorporate one of these scripts within the bash script, and run it manually.
Osor, I'm glad you came up with a sed method. I've run into a similar problem before (needing sed to take an action on the last occurrance of an expression in a stream), and the sed mailing list said there's no practical way of knowing when something appears last in a file (or last of a part of a file). I'll have to get familiar with what the holding pattern will do for me. That "N" command is not as useful as one would expect. Sed could really use a variant of the N command that will execute on every line (effectively processing every line twice), as opposed to just the even lines from the first line in the address range. |
Quote:
For example, here is how you would deal with the original problem in an ed script: Code:
echo -e '$-1s/,/ /\n,p' | ed - file For example, in a normal use of sed: Code:
sed -e 'commands' file Code:
line1 Code:
execute commands on "line1" Code:
sed -e '1h;1!H;$!d;${s/.*//;x};commands' file Code:
execute commands on "line1\nline2\nline3\n…\nlineN" Code:
sed -e '1h;1!H;$!d;${s/.*//;x};s/\(.*\),/\1 /' file So you could also do this (a proper/portable use of the hold buffer): Code:
sed -e '$!x;1d;${H;x};commands' Code:
execute commands on "line1" So you might use the above as a generic way to solve the similar problems you’ve run into before. For example, an alternate answer to your question is: Code:
sed -e '$!x;1d;${H;x};$s/,/ /' |
Hi.
The flexibility of perl allows us to avoid some of the complexity that osar discussed. In particular, this sample script essentially scans from the end of the file rather than scanning every line from the beginning. In a small file, this is not much of an improvement, but as the file gets larger, the improvement may be useful: regular expression matching can be expensive. The trade-off is that the entire file is held in an array. This is not a source of complexity in the script however, because perl manages its own memory. Naturally, for really large files, the load on the system may become more noticeable. Still, with all of that, the script is fairly small: Code:
#!/usr/bin/perl Code:
% ./p1 "," data1 Best wishes ... cheers, makyo |
With GNU Awk:
Code:
awk 'NR==FNR{if($0~/,/)x=FNR;next}FNR==x{$0=gensub(/,([^,]*)$/," \\1",1)}1' data data Code:
awk '{ x[NR] = $0 } /,/ { y = FNR |
Quote:
For example, Code:
perl -ne 'if(eof){$t.=$_;$t=~s/,/ /}print $t; $t=$_' file |
Oops, overlooked post
Hi.
I was doing some timings to see if there were any remarkable differences in the methods posted. As I read the posts, I see that I had over-looked rod's post #3 in perl. It is written in more idiomatic perl compared to the one I posted. I used the same technique as did he -- read entire file, search backwards from the end to find the last match, etc. Mine allowed the pattern (a small convenience, easily added), but also checked for a missing pattern, where rod's enters an unterminated loop; his re-writes the file, a good design for the Makefile inclusion. Both scripts are general in that they do not assume that the line to be changed is next-to-last. Apologies to rod for omitting his contribution -- it was unintentional. It also came to me later that osor's one-liner essentially uses "$t" as the equivalent of the sed hold buffer, but it is an improvement to omit the scan for every line (the first print of $t might be undefined, but it seemed to cause no trouble) ... cheers, makyo |
Quote:
If you want to resort to slurp-then-edit, what’s wrong with something like this? Code:
perl -w0pe 's/(.*),/$1 /s' file Code:
perl -w0pe 's/,(?=[^,]*$)/ /s' file Code:
perl -we '@t=reverse<>;s/,/ /&&last for@t;print reverse @t' file Code:
perl -w0pe '$_=reverse;s/,/ /;$_=reverse' file |
All times are GMT -5. The time now is 03:28 AM. |