Когда 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
, будет считаться ложным при использовании в булевом контексте:
Строковое значение следует считатьчисловая строкаесли это происходит из-за одного из следующих факторов:
Переменные поля
Входные данные от
getline()
функции
FILENAME
ARGV
элементы массива
ENVIRON
элементы массиваЭлементы массива, созданные
split()
функциейНазначение переменной командной строки
Присвоение переменной из другой числовой строковой переменной
и [если это похоже на число, прочитайте полное описаниездесь]
Пожалуйста, прочтите также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, являютсяполя(обычно разделенные пробелом).