2

I would like to know if it's possible to do the following thing only using awk: I am searching some regex in a file Fand I want to replace the string (S1) that matches the regex by another string (S2). Of course, it's easy to do that with awk. But ... my problem is that the value of S2 has to be obtained from another file that maps S1 to S2.

Example :

file F:

abcd 168.0.0.1 qsqsjsdfjsjdf
sdfsdffsd
168.0.0.2 sqqsfjqsfsdf

my associative table in another file

168.0.0.1 foo
168.0.0.2 bar

I want to get:

this result:

abcd foo qsqsjsdfjsjdf
sdfsdffsd
bar sqqsfjqsfsdf

Thanks for help !

edit: if my input file is a bit different, like this (no space before IP address):

file F:

abcd168.0.0.1 qsqsjsdfjsjdf
sdfsdffsd
168.0.0.2 sqqsfjqsfsdf

i can't use $1, $2 variables and search in the associative array. I tried something like that (based on birei proposition) but it did not work :

FNR < NR {
    sub(/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/, assoc [ & ] );
    print
}

Is there a way to search the matched string in the associative array (assoc[ & ] seems to be not valid) ?

1
  • If it is a one-off problem, put the table in the BEGIN section and query it then with your awk script. E.g., BEGIN { t[x1] = y; t[x2] = y; ... } { if ($1 in t) ...; } Commented Jul 7, 2012 at 18:31

1 Answer 1

5

One way. It's self-explanatory. Save data from the associative table in an array and in second file check for each field if it matches any key of the array:

awk '
    FNR == NR {
        assoc[ $1 ] = $2;
        next;
    }
    FNR < NR {
        for ( i = 1; i <= NF; i++ ) {
            if ( $i in assoc ) {
                $i = assoc[ $i ]
            }
        }
        print
    }
' associative_file F

Output:

bcd foo qsqsjsdfjsjdf                                                                                                                                                                                                                        
sdfsdffsd                                                                                                                                                                                                                                    
bar sqqsfjqsfsdf

EDIT: Try following awk script for IPs without spaces with their surrounding words. It's similar to previous one, but now it searches in the array and try to find an IP in any place of the line (default $0 for gsub) and substitutes it.

awk '
    FNR == NR {
        assoc[ $1 ] = $2;
        next;
    }
    FNR < NR {
        for ( key in assoc ) {
            gsub( key, assoc[ key ] )
        }
        print
    }
' associative_file F

Assuming infile with the conten of your second example of file F, output would be:

abcdfoo qsqsjsdfjsjdf                                                                                                                                                                                                                        
sdfsdffsd                                                                                                                                                                                                                                    
bar sqqsfjqsfsdf
Sign up to request clarification or add additional context in comments.

5 Comments

You should do if (i in assoc) instead of if (assoc[$i]) because the latter creates an entry in the array simply by referring to it. You can omit the FNR < NR selector since it will always be true (because of the next). You can omit the $0 = $0 since the $i = assignments do any field recomputing necessary.
@DennisWilliamson: Thank you. Good suggestions. I like the explicit comparison of FNR < NR, so I left it in the code. Others I agree that can be considered flaws, so I modified them.
thanks a lot ! it solved my problem and I learn that I have many things to learn about awk. so powerful tool ...
I added a small modification to the input file and I am now looking for a small modification to Birei proposition
@jean: I edited the answer but I suggest you to remove this answer as the accepted one at this time because the question is not solved yet and could avoid that some users also try to provide other solutions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.