awk
函数在文件名中看起来像这样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
}
内容awk.write
:
1
23
32
命令awk
是:
awk -f fun.awk awk.write
它没有给我任何结果?为什么?
更新
{
print f()
}
function f()
{
if(NR==1){s=$0}
if($0<p)
{s=$0}
{p=$0}
{ return s}
}
答案1
代码的两个版本都将small
在输入文件的每一行上运行该函数。如果您想找到整个文件中的最小数字,则只需在整个文件处理完毕后在最后运行该函数一次。您更新后的函数看起来可以正常工作并打印正确的输出三次,但这只是因为最小的数字位于第一行。如果您在此文件上运行它:
$ cat awk.write
10
9
8
您将得到以下输出:
awk -f fun.awk awk.write
10
9
8
这是因为每次运行该函数时,当前行号都小于已保存的行号,因此会打印出来。您需要使用一个END{}
块并在那里运行该函数:
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()
}
我还概括为使用NR
而不是3
这样它可以在任意数量的行上工作。您可以进一步简化为:
{
if(small=="" || $0<small){
small=$0
}
}
END{print small}
这与这一行相同:
awk '(small=="" || $0<small){small=$0}END{print small}' awk.write
答案2
if 子句中的语法错误,请使用:
if( a[i]<a[i+1]){
smal=a[i]
}else{
smal=a[i+1]
}
但是,它会打印每一行的值。
对于您的问题,更好的解决方案是:
sort -n file | head -1
- 这会将文件内容按数字升序排序,并
head
仅打印第一行。
或者如果必须是awk
:
awk 'NR==1{s=$0} $0<p{s=$0} {p=$0} END{print s}' file
NR==1{s=$0}
如果是第一行,则设置s
变量。$0<p{s=$0}
如果当前行小于前一行,则将s
变量设置为该值。{p=$0}
对于每一行,p
为下一次迭代设置(上一个)变量。END{print s}
当处理完所有行后,打印 的值s
。
编辑:所有这些都在一个函数中,看起来是:
awk 'function f(){ if(NR==1){s=$0} if($0<p){s=$0}p=$0} {f()} END{print s}' file