Реальная задача лучше всего решается путем инициализации ваших максимальных/минимальных значений не воображаемым «наименьшим» или «наибольшим» числом (, которое может быть не реализовано в используемой вами среде. используя, в данном случае awk
), но инициализируя его, используя фактические данные. Таким образом, всегда гарантирован значимый результат.
В вашем случае вы можете использовать самое первое значение, которое вы встретите (, то есть запись в первой строке )для инициализации max
и min
соответственно, добавив правило
NR==1{min=$1}
в ваш скрипт awk
. Тогда, если первое значение уже является минимальным, последующая проверка не перезапишет его, и в итоге будет выдан правильный результат. То же самое относится к поиску максимального значения, поэтому при комбинированном поиске вы можете указать
NR==1{max=min=$1}
Что касается причины, по которой ваш подход с inf
не работал с awk
, тогда как -inf
, казалось, работал, @steeldriver дал хорошее объяснение в комментарии к вашему вопросу, который я также резюмировать для полноты:
awk
переменные имеют "динамический тип", т.е.все может быть строкой или числом в зависимости от использования (, но awk
«запомнит», как оно использовалось в последний раз, и сохранит эту информацию для использования в следующей операции ). awk
попытается интерпретировать содержимое этой переменной как число и выполнить операцию, с которой переменная вводится как числовая в случае успеха. inf
не имеет специального значения в awk
, поэтому при использовании именно так это пустая переменная, которая будет равна 0 в арифметическом выражении, таком как -inf
. Следовательно, «максимальный поиск» с переменной max
, инициализированной значением -inf
, работает, если все ваши данные положительны, потому что -inf
— это просто 0 (и, таким образом, наименьшее не-отрицательное число ). ]. min
значением inf
приведет к инициализации переменной пустой строкой, поскольку отсутствует арифметическая операция, которая гарантировала бы автоматическое преобразование этой пустой строки в число. Поэтому в более поздних сравнениях
if ($1<min) min=$1
ввод, $1
, сравнивается со строковым значением, поэтому awk
также обрабатывает $1
как строку и выполняет лексикографическое сравнение, а не числовое.
Однако с лексикографической точки зрения нет ничего "меньше", чем пустая строка, и поэтомуmin
никогда не присваивается новое значение. Поэтому в разделе END
утверждение
print min
печатает (по-прежнему )пустую строку.
(*)см. ответ Стивена Китта о том, как строка с содержимым"inf"
может иметь значение в awk
.
Ваш подход не работает, потому что inf
не имеет особого значения в GNU AWK в режиме по умолчанию, отличном от -POSIX. В результате оно интерпретируется как имя переменной, и, поскольку переменной ничего не присвоено, ее значение равно 0 в арифметическом контексте и пустой строке в строковом контексте. Таким образом, ваш код найдет максимальное значение, только если оно положительное (, поскольку max
инициализируется в арифметическом контексте ), и не найдет минимальное значение (, поскольку min
инициализируется в строковом контексте. ); подробности см. в ответе AdminBee .
Чтобы определить минимальное и/или максимальное значение в файле (или потоке ), следует следовать советам, данным в ответе AdminBee .
Однако, если вы используете GNU AWK, вы можете вычислить log(0)
, чтобы инициализировать ваши переменные положительной или отрицательной бесконечностью, и использовать это аналогично вашему подходу:
BEGIN { max = log(0) }
$1 > max { max = $1 }
END { print max }
BEGIN { min = -log(0) }
$1 < min { min = $1 }
END { print min}
Единственное преимущество этого подхода по сравнению с инициализацией значений из первой строки заключается в том, что он обеспечивает отличительные результаты, когда никакие значения не обрабатываются — положительная или отрицательная бесконечность в конечном итоге являются надежными индикаторами того, что значение не было замечено. (Существуют и другие способы определить это, в том числе проверка на наличие пустой строки, а не 0 при инициализации с первой строки.)
С GNU AWK в режиме POSIX(POSIXLY_CORRECT=1
)или другими интерпретаторами AWK, совместимыми с POSIX -, такими как mawk
, предоставление "inf"
в виде строки в арифметическом контексте дает бесконечность,благодаряstrtod
:
BEGIN { max = "-inf" + 0 }
$1 > max { max = $1 }
END { print max }
BEGIN { min = "+inf" + 0 }
$1 < min { min = $1 }
END { print min}