0

This is the exact code I am running in my system with sh lookup.sh. I don't see any details within nawk block printed or written to the file abc.txt. Only I am here 0 and I am here 1 are printed. Even the printf in nawk is not working. Please help.

processbody() {
nawk '
NR == FNR {
split($0, x, "@")
country_code[x[2]] = x[1]
next
system(" echo " I am here ">>/tmp/abc.txt") 
}
{
CITIZEN_COUNTRY_NAME = "INDIA"
system(" echo " I am here 1">>/tmp/abc.txt") 
if (CITIZEN_COUNTRY_NAME in country_code) {
value = country_code[CITIZEN_COUNTRY_NAME]
system(" echo " I am here 2">>/tmp/abc.txt") 
} else {
value = "null"
system(" echo " I am here 3">>/tmp/abc.txt") 
}
system(" echo " I am here 4">>/tmp/abc.txt") 
print "found " value " for country name " CITIZEN_COUNTRY_NAME  >> "/tmp/standalone.txt"
} ' /tmp/country_codes.config
echo "I am here 5" >> /tmp/abc.txt
}

# Main program starts here
echo "I am here 0" >> /tmp/abc.txt
processbody 

And my country_codes.config file:

$ cat country_codes.config
IND@INDIA
IND@INDIB
USA@USA
CAN@CANADA
2
  • What do you want to accomplish? Commented Jun 14, 2011 at 4:00
  • Please give sample /tmp/abs.txt file along with required output. There is surely a simple awk solution for this. Commented Jun 14, 2011 at 7:20

3 Answers 3

1

That's some pretty interesting awk code. The problem is that your first condition, the NR == FNR one, is active for each record read from the first file - the country_codes.config file, but the processing action contains next so after it reads a record and splits it and saves it, it goes and reads the next record - not executing the second block of the awk script. At the end, it is done - nothing more to do, so it never prints anything.

This works sanely:

processbody() 
{   
    awk '
        {
        split($0, x, "@")
        country_code[x[2]] = x[1]
        #next
        }
    END {
        CITIZEN_COUNTRY_NAME = "INDIA"
        if (CITIZEN_COUNTRY_NAME in country_code) {
            value = country_code[CITIZEN_COUNTRY_NAME]
        } else {
            value = "null"
        }
        print "found " value " for country name " CITIZEN_COUNTRY_NAME
    } ' /tmp/country_codes.config
}   

# Main program starts here
processbody

It produces the output:

found IND for country name INDIA

As Hai Vu notes, you can use awk's intrinsic record splitting facilities to simplify life:

processbody()
{
    awk -F@ '
    { country_code[$2] = $1 }
    END {
        CITIZEN_COUNTRY_NAME = "INDIA"
        if (CITIZEN_COUNTRY_NAME in country_code) {
            value = country_code[CITIZEN_COUNTRY_NAME]
        } else {
            value = "null"
        }
        print "found " value " for country name " CITIZEN_COUNTRY_NAME
    } ' /tmp/country_codes.config
}

# Main program starts here
processbody
Sign up to request clarification or add additional context in comments.

2 Comments

This does the job - I want to have the array populated in awk to be used outsid ethis awk (actually in another nawk which reads 20,000 records in a file and which has a value INDIA as one of the attributes - I am sorry that I cant let you know the complete layout of the file - In short processbody should have the awk block you have mentioned above and have the array populated with Country name and ISO value and I would be using this array in my actual nawk to substitute country name with country ISO - Thanks
@user548432: Look up getline in your awk manual. At least in gawk (GNU Awk) you can use getline < /tmp/country_codes.config in a BEGIN block to preload your array. If your version can't do that by some mechanism, then consider upgrading to GNU Awk or changing to Perl or Python to do the job. You can't have one awk script populating the array for another. Alternatively again, you might be able to use the FILENAME variable to detect when you're reading the config file and when you're reading other stuff, and then specify the config file and the other data files on the command line.
0

I don't know what you want to accomplish, but let me guess: if country is INDIA, then print the following output:

found IND for country name INDIA

If that is the case, the following code will accomplish that goal:

awk -F@ '/INDIA/ {print "found " $1 " for country name " $2 }' /tmp/country_codes.config 

The -F@ flag tells awk (or nawk) to use @ as the field separator.

6 Comments

I already have a nawk block which reads a file with 20000 records in which one of the field is country and I want a small block for ISO code lookup - I thought of having it in a separate array and then use it in the nawk block whenever i get the country - Hope this helps
@user549432 Can you provide sample of the two files as well as required output. Without that we can only guess what you are after.
@ Ripat - Code that Jonathan posted above does the job - For your question - I want to have the array populated with Country name and ISO in awk to be used outside this awk (actually in another nawk which reads 20,000 records in a file and which has a value INDIA as one of the attributes - I am sorry that I cant let you know the complete layout of the file - In short processbody should have the awk block you have mentioned above and have the array populated with Country name and ISO value and I would be using this array in my actual nawk to substitute country name with country ISO - Thanks
@Hai Vu - Can I use this inside nawk block - I am not able to do it as it is giving parsing errors - Can you pls help me
@user549432: I don't know nawk. Are the syntax similar? What kind of error you received?
|
0

@user549432 I think that you want one awk script that first reads in the country codes file and builds the associative array, and then reads in the input files (not @ delimited) and does a substitution?

if so, let's assume that /tmp/country_codes.config has:

IND@INDIA
IND@INDIB
USA@USA
CAN@CANADA

and /tmp/input_file (not @ delimited) has:

I am from INDIA
I am from INDIB
I am from CANADA

Then, we can have a nawk script like this:

nawk '

BEGIN {
        while (getline < "/tmp/country_codes.config")
        {
          split($0,x,"@")
          country_code[x[2]] = x[1]
        }
      }

  { print $1,$2,$3,country_code[$4]}

' /tmp/input_file

The output will be:

I am from IND
I am from IND
I am from CAN

3 Comments

Yup the requirement you have stated is right - Thanks a lot for your time -The problem with the above code is the array is built within nawk block - Wouldnt this pice run for every record in the input file and getline/grep would be slow to be processed for every 20 K records in the input file - I already have working solution with getline- I would want this associative array outside my existing nawk - build a array and then use that array to lookup my country using the built array in my nawk block
I put the getline building the associative array inside the BEGIN {} block. The BEGIN {} block is just run once, before all the input is processed. So it will only build the associative array once.
@ Praveen what is Country_code[$4] - After the begin block assume somehow I get the value India in COUNTRY_NAME field - Can I do something like COUNTRY_NAME in Country_code array list ...?

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.