awk's gsub variable in replacement

I been trying to figure out how to use element of array as a replacement pattern. This works as I expected:

$ echo "one two three" | awk '{
  gsub(/wo/,"_BEG_&_END_",$2); 
  print }'
one t_BEG_wo_END_ three 
$ echo "one two three" | awk '{
  tmp="foo"; 
  gsub(/wo/,"_BEG_" tmp "_END_",$2); 
  print}'
one t_BEG_foo_END_ three
$ echo "one two three" | awk '{
  tmp["wo"]="foo"; 
  gsub(/wo/,"_BEG_" tmp["wo"] "_END_",$2); 
  print}'
one t_BEG_foo_END_ three
$ echo "one two three" | awk '{
  tmp["wo"]="foo"; 
  a="wo"; 
  gsub(/wo/,"_BEG_" tmp[a] "_END_",$2); 
  print}'
one t_BEG_foo_END_ three

So why does this not?

$ echo "one two three" | awk '{tmp["wo"]="foo"; gsub(/wo/,"_BEG_" tmp["&"] "_END_",$2); print}'
one t_BEG__END_ three

How do I access the element of array tmp[<captured_string>]?
Thank you.

Think your going to need to use match with RSTART and RLENGTH:

$ echo "one two three" | awk '{tmp["wo"]="foo";
if(match($0, "wo")) {
    fnd=substr($0, RSTART, RLENGTH);
    print substr($0, 1, RSTART-1) "_BEG_" tmp[fnd] "_END_" substr($0,RSTART+RLENGTH)
}}'
one t_BEG_foo_END_ three
1 Like

Thanks Chubler.
Confusing part is, that i can use array inside gsub replacement argument like

gsub(/pattern/,array[var],$0);

, but not array["&"].... like

gsub(/pattern/,array["&"],$0); 

This is not confusing if you think of gsub as a function that takes 3 parameters. The value of the 2nd parameter has to be evaluated before the function is called.

As you can see the value of what's being replaced cannot be known until the funtion returns and at this point the 2nd parameter has already be evaluated.

1 Like

Ahhh... now it makes sense. (Although I had to re-read your post a few times :slight_smile: )

I guess I was hoping that the function would take as a second argument a pointer of the array, then the element could be retrieved from within, after the captured pattern is known.
(I'm thinking in terms of C-style array, whereas assoc. arrays of awk are quite different, aren't they?)
Thanks a lot once again.

You could always write your own function to do this:

awk 'function arrayrep(pattern, array, string) {
    while (match(string, pattern)) {
        fnd=substr(string, RSTART, RLENGTH);
        string = substr(string, 1, RSTART-1) array[fnd] substr(string,RSTART+RLENGTH)}
    return string
}
BEGIN {
  G["%NAME1%"]="Jack"
  G["%NAME2%"]="Jill"
  print arrayrep("%[^%]*%", G, "%NAME1% and %NAME2% went up the hill ... %NAME1% fell down") }'