LucaZ
LucaZ

Reputation: 87

Count substitutes per line

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

Answers (3)

Frank-Rene Sch&#228;fer
Frank-Rene Sch&#228;fer

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

Sobrique
Sobrique

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

James Brown
James Brown

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

Related Questions