如果 $1 的值为 0(数字零),为什么 awk 的行为不同?

如果 $1 的值为 0(数字零),为什么 awk 的行为不同?

当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”(第一)

[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'为什么我使用and时会出现差异var=1; echo $var | awk '$1=$1'?除了 之外,所有数字都工作正常0

版本:

  • GNU bash,版本 4.2.46
  • GNU Awk 4.0.2
  • coreutils-8.22-24.el7.x86_64

答案1

来自GNU Awk 用户指南

赋值是一个表达式,因此它有一个值——与被赋值的值相同。因此,“z = 1”是值为 1 的表达式。

所以

  • echo 0 | awk '$1=$1'该模式的计算结果为 0 (FALSE)

  • echo 1 | awk '$1=$1'print该模式的计算结果为 1 (TRUE),并且执行默认操作

答案2

我认为这不是数值的问题:标准转换可以解决这个问题(至少在这里)。

OP 显示了四种不同的 awk 代码,所有变体都为:pattern { action }

(一) 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"'


作为另一个怪癖,请注意,至少在某些实现中,$0如果对子字段的赋值导致重新计算(当前输入记录),则它会丢失其神奇的“数字字符串”属性:

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

这似乎没有被标准涵盖,尽管它与标准 awk 所基于的 nawk/bwk 的行为相匹配(但不是 mawk 的行为)。

此外,允许 awk 实现将输入中的NAN,INF和识别INFINITY为相应的浮点数,尽管对此的支持参差不齐且不一致。您可能仍然被咬伤,例如。

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

不在 FreeBSD 的 awk 中打印任何内容(bwk、original-awk)。

答案4

因为 $0 是整个记录(完整行),$1,$2,是领域(通常用空格分隔)在其中。

相关内容