如果 $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,是領域(通常用空格分隔)在其中。

相關內容