Поплавковое сравнение в 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 позже.

Другие вопросы по тегам