1

awk function looks like this in a file name fun.awk:

{
print small()
}
function small()

{
a[NR]=$0

smal=0

for(i=1;i<=3;i++)
{
if( a[i]<a[i+1])

smal=a[i]

else

smal=a[i+1]

}
return smal
}

The contents of awk.write:

1
23 
32

The awk command is:

awk -f fun.awk awk.write

It gives me no result? Why?

update

{

print f()
}
function f()

{


if(NR==1){s=$0}


if($0<p)

{s=$0}

{p=$0}

 { return s}

}
1

Both versions of your code will run the small function on every line of the input file. If you want to find the smallest number in the entire file, you need to run the function only once and at the end, after the entire file has been processed. Your updated function looks like its working and printing the correct output three times but that's only because the smallest number is on the first line. If you run it on this file:

$ cat awk.write
10
9
8

You will get this output:

awk -f fun.awk awk.write
10
9
8

This is because every time the function is run, the current line's number is smaller than what has been saved, so it is printed. You need to use an END{} block and run the function there:

function small(){
    for(i=1;i<=NR;i++)
    {
      ## If smal is not set or if it is greater than a[i]
      if(smal=="" || a[i]<=smal)
        smal=a[i]
    }
return smal
}
{
    ## NR is the current line number. This saves the current line
    ## in the array a.
    a[NR]=$0
}
## This will be executed only after everything has been read
END{
    print small()
}

I also generalized to use NR instead of 3 so it can work on any number of lines. You could further simplify to just:

{
    if(small=="" || $0<small){
    small=$0
    }
}
END{print small}

Which is the same as this one-liner:

awk '(small=="" || $0<small){small=$0}END{print small}' awk.write   
  • Thanks for such a comprehensive reply. In your comments you mentioned ` ## NR is the current line number. This saves the current line` but is $0 a record buffer it contains the entire contents. The first record is NR=1 please clarify? – asad Jan 10 '16 at 13:12
  • 1
    @asad NR is the line number and $0 the line's contents. So, if the first line is foo, [NR]=$0 will run a[1]=foo. I'm just using NR as an easy way of getting array indices. – terdon Jan 10 '16 at 13:34
1

The syntax in the if-clause is wrong, use:

if( a[i]<a[i+1]){
  smal=a[i]
}else{
  smal=a[i+1]
}

But, it will print the value for every line.


A better solution for you problem would be:

sort -n file | head -1
  • This sorts the file contents numerically ascending, and head prints only the first line.

Or if it must be awk:

awk 'NR==1{s=$0} $0<p{s=$0} {p=$0} END{print s}' file
  • NR==1{s=$0} if it's the first line, set the s variable.
  • $0<p{s=$0} if the current line is smaller than the previous one, set the s variable to that value.
  • {p=$0} for each line, set the p (previous) variable for the next iteration.
  • END{print s} when all line are processed, print the value of s.

Edit: all that in a function, would look:

awk 'function f(){ if(NR==1){s=$0} if($0<p){s=$0}p=$0} {f()} END{print s}' file
  • thanks, so this code with awk can be placed into function as well? – asad Jan 8 '16 at 13:43
  • i want to do as part of fucntion not in-line awk – asad Jan 8 '16 at 13:48
  • I tried it doesn't work also there is a missing { in p=$0 – asad Jan 8 '16 at 14:08
  • also, my way of using it as function is different awk -f fun.awk awk.write – asad Jan 8 '16 at 14:12
  • i revised the code for function see main question in update section but problem is that it prints x3. – asad Jan 8 '16 at 14:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.