Reputation: 87
I have a (BIG) file containing lines like:
foobar {} foo{} bar{} foobar{}{}
foo {} foodfg{} bar{} foogfdbar{}
line without brackets
foobdgar {} fdfgoo{} bga foodfbar{}{}
fdfgoobar {} fdfoo dbar{} fooddbar
now I want to replace every {} with {$MATCH_COUNT} for each line seperately
Meaning the output should look like this:
foobar {0} foo{1} bar{2} foobar{3}{4}
foo {0} foodfg{1} bar{2} foogfdbar{3}
line without brackets
foobdgar {0} fdfgoo{1} bga foodfbar{2}{3}
fdfgoobar {0} fdfoo dbar{1} fooddbar
How can I do this in perl or awk? I am not an expert in these languages so I would highly appreciate it if you could explain shortly what the code is doing.
My solutions so far that do not work like I intended:
Perl:
cat test.properties | perl -e 'while(<>){ $c=0; while(/{}/g){print "{$c}"; $c++} print "\n"}'
(replaces it like i want but doesn't keep the unmatched stuff)
Awk:
cat test.properties | awk '{ print "{" gsub(/{}/, "") "}" }'
(replaces every line with a complete count - not what I want)
Upvotes: 0
Views: 79
Reputation: 3352
FS = field seperator.
NF = Number of fields that has been built splitting the line.
'printf' is like the C-Standard function.
cat test.properties | awk 'BEGIN{ FS="{}" }{ for(i=1;i<NF;++i) { printf "%s{%i}", $i, i-1; } printf "\n"; }'
Upvotes: 2
Reputation: 53498
The thing you need here, is the e
flag to a pattern substitute. This says 'evaluate' and lets you use code expressions in regex replacements. Like $count++
for example :)
E.g.:
#!/usr/bin/env perl
use strict;
use warnings;
while ( <DATA> ) {
my $count = 0;
s/{}/"{".$count++."}"/ge;
print
}
__DATA__
foobar {} foo{} bar{} foobar{}{}
foo {} foodfg{} bar{} foogfdbar{}
line without brackets
foobdgar {} fdfgoo{} bga foodfbar{}{}
fdfgoobar {} fdfoo dbar{} fooddbar
Seems to do what you want.
To simpify this down:
perl -pe '$c=0; s/{}/"{".$c++."}"/ge' text.properties
Note the -p
flag to perl - it wraps your code in a loop, such that it works a lot like 'sed' would (e.g. while ( <> ) {
and print
each line as you go) which is what you're trying to do in your example 'by hand'.
You could, if you were so inclined also use the -i
flag for in place editing.
I would also note - cat | awk
or perl
is redundant - both take file arguments when executing things.
Upvotes: 6
Reputation: 37424
In awk:
$ awk '{i=0; while(sub(/{}/,"{" i++ "}"));}1' file
foobar {0} foo{1} bar{2} foobar{3}{4}
foo {0} foodfg{1} bar{2} foogfdbar{3}
line without brackets
foobdgar {0} fdfgoo{1} bga foodfbar{2}{3}
fdfgoobar {0} fdfoo dbar{1} fooddbar
Explained:
{
i=0 # initialize i to 0
while(sub(/{}/,"{" i++ "}")); # while replacing with increasing i do nothing else
} 1 # implicit print
Upvotes: 1