値が 0 (数字のゼロ) の場合、awk は $1 に対して異なる動作をするのはなぜですか?

値が 0 (数字のゼロ) の場合、awk は $1 に対して異なる動作をするのはなぜですか?

awkが「0」入力として、場合によっては異なる動作をします。以下のコード:

var=$1
echo ""; echo -n 'o/p of $1=$1 ==>'; echo $var | awk '$1=$1'
echo "";echo -n 'o/p of {$1=$1;print} ==>';echo $var | awk '{$1=$1;print}'
echo "";echo -n 'o/p of $1==$1 ==>';echo $var | awk '$1==$1'
echo "";echo -n 'o/p of {$1==$1;print} ==>';echo $var | awk '{$1==$1;print}'

出力は「0」(数字のゼロ):

[root@host ~]# sh /tmp/te.sh 0

o/p of $1=$1 ==>
o/p of {$1=$1;print} ==>0

o/p of $1==$1 ==>0

o/p of {$1==$1;print} ==>0
[root@GORJALA ~]#

出力は「1」(数字の1):

[root@host ~]# sh /tmp/te.sh 1

o/p of $1=$1 ==>1

o/p of {$1=$1;print} ==>1

o/p of $1==$1 ==>1

o/p of {$1==$1;print} ==>1
[root@host ~]#

var=0; echo $var | awk '$1=$1'と を使用するとなぜ違いがあるのですかvar=1; echo $var | awk '$1=$1'? を除くすべての数値は正常に動作します0

バージョン:

  • GNU bash、バージョン 4.2.46
  • GNU awk 4.0.2
  • コアユーティリティ-8.22-24.el7.x86_64

答え1

からGNU Awk ユーザーズガイド:

代入は式なので、代入される値と同じ値を持ちます。したがって、「z = 1」は値が 1 である式です。

それで

  • echo 0 | awk '$1=$1'パターンは 0 (FALSE) と評価されます

  • echo 1 | awk '$1=$1'パターンは1(TRUE)と評価され、デフォルトのアクションprintが実行されます

答え2

これは数値の問題ではないと思います。標準的な変換によってそれが処理されます (少なくともここでは)。

OP は 4 つの異なる awk コードを示していますが、すべてパターン { アクション } のバリエーションです。

(a) 1ドル = 1ドル

これは$1を自分自身に再割り当てします。これはブールテストではなく、(事実上)何もせず、$1の値を返します。$1が0の場合、パターンは次のようになります。間違いそしてデフォルト印刷アクションは完全にスキップされます. $1がゼロでない場合、入力が印刷される

(b) { $1 = $1; 印刷; }

これは$1を自分自身に再割り当てしますが、これも何もしません。パターンがない場合、アクションが実行され、入力は常に印刷される

(c) $1 == $1

これはブール式であり、常に真実0は0、1は1(そしてツチブタはツチブタです)。アクションがない場合、入力は常に印刷される

(d) { $1 == $1; 印刷; }

パターンはありません。比較は真のブール値に評価されますが、これは破棄されます。入力は常に印刷される

答え3

既存の回答では、なぜ

echo 0 | awk '$0="0"'
echo 0 | awk '$0=substr($0,1)'
echo 0 | awk '$0=$0""'

すべて印刷されます0が、

echo 0 | awk '$0'
echo 000 | awk '$0'

何も印刷されませんが、すべてのケースでパターン式は と評価されます0

0一方で真実であり、他方で偽であるのはなぜでしょうか?

これは、「フィールド変数」(演算子の結果$)が特別なケース、そして(可能な場合)自動的に変換されます数値文字列が数値的に と等しい場合0、ブールコンテキストで使用すると false とみなされます。

文字列値は、数値文字列次のいずれかに該当する場合:

  1. フィールド変数

  2. getline()関数からの入力

  3. FILENAME

  4. ARGV配列要素

  5. ENVIRON配列要素

  6. split()関数によって作成された配列要素

  7. コマンドライン変数の割り当て

  8. 別の数値文字列変数からの変数割り当て

そして[数字のように見える場合は、説明全体を読んでくださいここ]

以下もお読みくださいRATIONALE数値文字列の概念とこの特殊なケースが必要だった理由、特に のような比較がecho 0 000 | awk '$1==$2'true であるが ではないという部分についてecho 0 | awk '$1=="000"'


もう 1 つの奇妙な点として、少なくとも一部の実装では、$0サブフィールドへの割り当てによって再計算されると、(現在の入力レコード) はその魔法の「数値文字列」プロパティを失うことに注意してください。

$ echo 0 | gawk '{$1=0} $0'
0

これは標準ではカバーされていないようですが、標準 awk のベースとなっている nawk/bwk の動作と一致しています (ただし mawk の動作は一致していません)。

NANまた、awk 実装では、入力内の 、 を対応する浮動小数点数として認識できますINFが、このサポートは不完全で一貫性がありません。たとえば、次のような問題が発生する場合があります。INFINITY

echo But his daughter named Nan | awk '$NF'

FreeBSD の awk (bwk、オリジナル awk) では何も印刷されません。

答え4

0ドルは全記録(完全な行)、$1、$2は田畑(通常は空白で区切られます) が含まれます。

関連情報