Print smallest integer from file using awk custom function?

`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<a[i+1])
    
    smal=a
    
    else
    
    smal=a[i+1]
   
    }
    return smal
    }

The contents of `awk.write`:

The `awk` command is:

awk -f fun.awk awk.write

It gives me no result? Why?

Hello lazerz,

Could you please try following and let me know if this helps you. Let's say we have following Input_file.

 
1
23
32
67
78
89
100
234
12
0
-1
12
233
13
15
13
 

Then following code may help us to achieve as your request.

awk 'NF{A[NR]=$0;n=NR} END{for(i=1;i<=n;i++){Y=Y<A?Y:A};print Y}'  Input_file

Output will be as follows.

 -1
 

Thanks,
R. Singh

Thxs, i can do with one-liner I need to do in function.

---------- Post updated at 10:00 AM ---------- Previous update was at 09:46 AM ----------

can this same be translate into function?

Saying the above script gives you no result is misleading. With a three line input file, it produces three lines of output (each output line being an empty line). You haven't said what you are trying to do with this script (or function). As written, it appears that the intent is to print the smallest value read so far for each line read. I.e., the output from the 1st line read will be the first line read, the output from the 2nd line read will be the smaller of the 1st two values read, and the output from the 3rd line read will be the smallest of the 1st three values read.

But, your function doesn't look for the smallest value in the number of lines read; instead it looks for the smaller value in the 3rd and 4th values (in an array that never has more than three values included when reading a three line input file). And, since the 4th value in that array is the default empty string assumed by any unassigned variable (which is treated as a zero value when compared to an integer), the result of each call to your function was an empty string.

Rewriting fun.awk to only use elements of the array that have actually been assigned variables (and reformatting to make the structure more obvious):

{
    print small()
}
function small() {
    smal=a[NR]=$0
    for(i = 1; i < NR; i++) {
	if(a < smal)
	    smal=a
    }
    return smal
}

makes the command line:

awk -f fun.awk awk.write

produce the output:

1
1
1

And if the data sample suggested in post #2 is stored in a file named file , the command:

awk -f fun.awk file

produces the output:

1
1
1
1
1
1
1
1
1
0
-1
-1
-1
-1
-1
-1

If the goal of the script is to just print the smallest value read (and a function is required rather than keeping track of the smallest value seen while reading the data), that would be written as:

{
    small()
}
function small() {
    smal=a[NR]=$0
    for(i = 1; i < NR; i++) {
	if(a < smal)
	    smal=a
    }
    return smal
}
END {
    print small()
}

or, MUCH more efficiently, as:

{
    a[NR] = $0
}
function small() {
    smal = a[NR]
    for(i = 1; i < NR; i++) {
	if(a < smal)
	    smal=a
    }
    return smal
}
END {
    print small()
}

And, of course, if you don't insist on a function, a better way to do it if you want to use awk would be:

NR == 1 {
	small = $0
	next
}
$0 < small {
	small = $0
}
END {	print small
}
1 Like

Thank you so much Don you explained the code like a good and sincere teacher. I have nothing more to say.