Почему awk ведет себя по-другому для $1, если значение равно 0 (число ноль)?

Почему awk ведет себя по-другому для $1, если значение равно 0 (число ноль)?

Когда 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'и 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' — это выражение со значением один.

Так

  • echo 0 | awk '$1=$1'шаблон оценивается как 0 (ЛОЖЬ)

  • echo 1 | awk '$1=$1'шаблон оценивается как 1 (ИСТИНА) и printвыполняется действие по умолчанию

решение2

Я не думаю, что дело в числовом значении: об этом позаботятся стандартные преобразования (по крайней мере, здесь).

OP показывает четыре разных кода awk, все вариации на тему: pattern { action }

(а) 1 доллар = 1 доллар

Это переназначает $1 самому себе. Это не булев тест, это пустая операция (фактически), и она возвращает значение $1. Если $1 — это 0, шаблонЛОЖЬи по умолчаниюдействие печати полностью пропускается. Если $1 не равен нулю,ввод печатается.

(б) { $1 = $1; распечатать; }

Это переназначает $1 самому себе, также бездействуя. При отсутствии шаблона действие выполняется, а вводвсегда печатается.

(с) 1 доллар == 1 доллар

Это булево выражение, котороевсегда правда. 0 это 0 и 1 это 1 (и трубкозуб это трубкозуб). При отсутствии действия вводвсегда печатается.

(г) { $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, будет считаться ложным при использовании в булевом контексте:

Строковое значение следует считатьчисловая строкаесли это происходит из-за одного из следующих факторов:

  1. Переменные поля

  2. Входные данные от getline()функции

  3. FILENAME

  4. ARGVэлементы массива

  5. ENVIRONэлементы массива

  6. Элементы массива, созданные split()функцией

  7. Назначение переменной командной строки

  8. Присвоение переменной из другой числовой строковой переменной

и [если это похоже на число, прочитайте полное описаниездесь]

Пожалуйста, прочтите такжеRATIONALEпо причинам, по которым была необходима концепция числовых строк и этот особый случай, особенно часть о сравнении, например, « echo 0 000 | awk '$1==$2'истина», но не «...» echo 0 | awk '$1=="000"'.


Еще одна странность: обратите внимание, что, по крайней мере в некоторых реализациях, $0(текущая входная запись) теряет свое магическое свойство «числовой строки», если присвоение подполю приводит к его пересчету:

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

Похоже, это не охвачено стандартом, хотя соответствует поведению nawk/bwk, на котором основан стандарт awk (но не mawk).

Также реализациям awk разрешено распознавать NAN, INFи INFINITYво входных данных как соответствующие числа с плавающей точкой, хотя поддержка этого неравномерна и непоследовательна. Вас все еще могут укусить, например.

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

ничего не печатается в awk FreeBSD (bwk, original-awk).

решение4

Потому что $0 — этовся запись(полная строка), $1, $2, являютсяполя(обычно разделенные пробелом).

Связанный контент