awkカスタム関数を使用してファイルから最小の整数を印刷しますか?

awkカスタム関数を使用してファイルから最小の整数を印刷しますか?

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入力ファイルの各行で関数を実行します。ファイル全体の最小数を見つけるには、ファイル全体を処理して最後に一度だけ関数を実行します。更新された関数は正しく機能し、正しい出力を3回印刷するように見えますが、これは最小数が最初の行にあるためです。このファイルで実行すると:

$ 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

編集する:これらすべてを1つの関数として表現すると、次のようになります。

awk 'function f(){ if(NR==1){s=$0} if($0<p){s=$0}p=$0} {f()} END{print s}' file

関連情報