Поплавковое сравнение в awk и mawk
Я не могу понять, почему сравнение чисел с плавающей точкой не работает в Mawk:
mawk '$3 > 10' file.txt
[...]
9_6_F-repl 24834 38.8699
9_6_F 56523 17.9344
9_7_F 3196 3.68367
9_9_F 2278 2.37445
9_annua_M-merg 122663 163.557
9_huetii_F-merg 208077 172.775
[...]
В то время как это прекрасно на awk, вот так:
awk '{if ($3 > 10) print $1}' file.txt
Я явно делаю что-то не так, но не могу понять, что.
2 ответа
Это терпит неудачу, если файл имеет терминаторы строки CRLF. Удалить \r
первый:
$ file foo
foo: ASCII text, with CRLF line terminators
$ mawk 'sub(/\r/,"") && ($3 > 10)' foo
9_6_F-repl 24834 38.8699
9_6_F 56523 17.9344
9_annua_M-merg 122663 163.557
9_huetii_F-merg 208077 172.775
В качестве альтернативы вы можете использовать dos2unix
или такой.
EDIT2: Если вы используете локаль с запятой в качестве десятичного разделителя, это влияет на сравнения с плавающей запятой в mawk.
В этом случае вы можете:
1) установить локаль на
LANG="en_US.UTF-8"
или же
2) заменить десятичные разделители на запятые и передать его в mawk:
mawk '$3 > 10' <(cat file.txt | sed -e "s/\./,/")
Вам не нужно устанавливать локаль, но необходимо учитывать странный или ошибочный ввод:
Если на входе есть точка или любой символ, который имеет порядок байтов выше, чем ASCII «1» (что МНОГО вещей):
9_6_F-repl 24834 9.
9_6_F 56523 9.
9_annua_M-merg 122663 9.
9_huetii_F-merg 208077 9.
9_annua_M-merg 122663 :5.333
это совершенно не даст правильного результата, поскольку сравнивается как строка, где ASCII "9" больше, чем ASCII "1":
mawk2 'sub("\r*",_)*(10<$3)'
9_6_F-repl 24834 9.
9_6_F 56523 9.
9_annua_M-merg 122663 9.
9_huetii_F-merg 208077 9.
9_annua_M-merg 122663 9.
9_annua_M-merg 122663 :5.333
Чтобы исправить это, просто добавьте
+
следующий на
$3
:
mawk 'sub("\r*",_)*(10<+$3)'
Если вам плевать на архаику
gawk -P/-c/-t
режимы, то это еще проще:
mawk '10<+$3' RS='\r?\n'
Позвольте позаботиться о
\r
:: CR от вашего имени. Разместив
?
в регулярном выражении RS вы можете пропустить все шаги по использованию
iconv
или же
dos2unix
или изменение
locale
настройки ::
-
RS
—-->ORS
справился бы без проблем
Таким образом, исходный входной файл остается нетронутым на тот случай, если вам по какой-то причине понадобятся эти CR позже.