dig_123
dig_123

Reputation: 2358

Numeric expression in if condition of awk

Pretty new to AWK programming. I have a file1 with entries as:

15>000000513609200>000000513609200>B>I>0011>>238/PLMN/000100>File Ef141109.txt>0100-75607-16156-14 09-11-2014
15>000000513609200>000000513609200>B>I>0011>Danske Politi>238/PLMN/000200>>0100-75607-16156-14 09-11-2014
15>000050354428060>000050354428060>B>I>0011>Danske Politi>238/PLMN/000200>>4100-75607-01302-14 31-10-2014

I want to write a awk script, where if 2nd field subtracted from 3rd field is a 0, then it prints field 2. Else if the (difference > 0), then it prints all intermediate digits incremented by 1 starting from 2nd field ending at 3rd field. There will be no scenario where 3rd field is less than 2nd. So ignoring that condition.

I was doing something as:

 awk 'NR > 2 { print p } { p = $0 }' file1 | awk -F">" '{if ($($3 - $2) == 0) print $2; else l = $($3 - $2); for(i=0;i<l;i++) print $2++; }'

(( Someone told me awk is close to C in terms of syntax ))

But from the output it looks to me that the String to numeric or numeric to string conversions are not taking place at right place at right time. Shouldn't it be taken care by AWK automatically ?

The OUTPUT that I get:

513609200
513609201
513609200

Which is not quiet as expected. One evident issue is its ignoring the preceding 0s.

Kindly help me modify the AWK script to get the desired result.

NOTE:

awk 'NR > 2 { print p } { p = $0 }' file1 is just to remove the 1st and last entry in my original file1. So the part that needs to be fixed is:

awk -F">" '{if ($($3 - $2) == 0) print $2; else l = $($3 - $2); for(i=0;i<l;i++) print $2++; }'

Upvotes: 1

Views: 2634

Answers (3)

peak
peak

Reputation: 116730

For anyone who does not have ready access to gawk with bigint support, it may be simpler to consider other options if some kind of "big integer" support is required. Since ruby has an awk-like mode of operation, let's consider ruby here.

To get started, there are just four things to remember:

  1. invoke ruby with the -n and -a options (-n for the awk-like loop; -a for automatic parsing of lines into fields ($F[i]));
  2. awk's $n becomes $F[n-1];
  3. explicit conversion of numeric strings to integers is required;
  4. To specify the lines to be executed on the command line, use the '-e TEXT' option.

Thus a direct translation of:

awk -F'>' '{for(i=$2;i<=$3;i++) print i}' file

would be:

ruby -an -F'>' -e '($F[1].to_i .. $F[2].to_i).each {|i| puts i }' file

To guard against empty lines, the following script would be slightly better:

($F[1].to_i .. $F[2].to_i).each {|i| puts i } if $F.length > 2

This could be called as above, or if the script is in a file (say script.rb) using the incantation:

ruby -an -F'>' script.rb file

Given the OP input data, the output is:

513609200
513609200
50354428060

The left-padding can be accomplished in several ways -- see for example this SO page.

Upvotes: 0

glenn jackman
glenn jackman

Reputation: 246807

In awk, think of $ as an operator to retrieve the value of the named field number ($0 being a special case)

  • $1 is the value of field 1
  • $NF is the value of the field given in the NF variable

So, $($3 - $2) will try to get the value of the field number given by the expression ($3 - $2).

You need fewer $ signs

awk -F">" '{
    if ($3 == $2) 
        print $2
    else {
        v=$2
        while (v < $3) 
            print v++
    }
}'

Upvotes: 2

karakfa
karakfa

Reputation: 67497

Normally, this will work, but your numbers are beyond awk integer bounds so you need another solution to handle them. I'm posting this to initiate other solutions and better illustrate your specifications.

$ awk -F'>' '{for(i=$2;i<=$3;i++) print i}' file

note that this will skip the rows that you say impossible to happen

A small scale example

$ cat file_0
x>1000>1000>etc
x>2000>2003>etc
x>3000>2999>etc

$ awk -F'>' '{for(i=$2;i<=$3;i++) print i}' file_0
1000
2000
2001
2002
2003

Apparently, newer versions of gawk has --bignum options for arbitrary precision integers, if you have a compatible version that may solve your problem but I don't have access to verify.

Upvotes: 1

Related Questions