awk 和 mawk 中的浮点数比较
Float comparison in awk and mawk
我无法理解为什么浮点数比较在 mawk 中不起作用:
mawk ' > 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 ( > 10) print }' file.txt
我显然在这里做错了什么,但我不明白是什么。
如果文件有 CRLF 行终止符,则失败。先去掉\r
:
$ file foo
foo: ASCII text, with CRLF line terminators
$ mawk 'sub(/\r/,"") && ( > 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 ' > 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
这将完全无法产生正确的结果,因为 </code> 正在作为字符串进行比较,其中 ASCII“9”大于 ASCII“1”:</p>
<pre><code>mawk2 'sub("\r*",_)*(10<)'
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
要纠正它,只需在 </code> 旁边添加 <code>+
:
mawk 'sub("\r*",_)*(10<+)'
如果您不太喜欢陈旧的 gawk -P/-c/-t
模式,那么它甚至更简单:
mawk '10<+' RS='\r?\n'
让 ORS
代表您处理 \r
::CR。通过将 ?
放在 RS 正则表达式中,您可以跳过有关使用 iconv
或 dos2unix
或更改 locale
设置的所有步骤 ::
RS
——>ORS
会无缝处理
这样原始输入文件将保持完整,以防您以后出于某种原因需要这些 CR。
我无法理解为什么浮点数比较在 mawk 中不起作用:
mawk ' > 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 ( > 10) print }' file.txt
我显然在这里做错了什么,但我不明白是什么。
如果文件有 CRLF 行终止符,则失败。先去掉\r
:
$ file foo
foo: ASCII text, with CRLF line terminators
$ mawk 'sub(/\r/,"") && ( > 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 ' > 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
这将完全无法产生正确的结果,因为 </code> 正在作为字符串进行比较,其中 ASCII“9”大于 ASCII“1”:</p>
<pre><code>mawk2 'sub("\r*",_)*(10<)'
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
要纠正它,只需在 </code> 旁边添加 <code>+
:
mawk 'sub("\r*",_)*(10<+)'
如果您不太喜欢陈旧的 gawk -P/-c/-t
模式,那么它甚至更简单:
mawk '10<+' RS='\r?\n'
让 ORS
代表您处理 \r
::CR。通过将 ?
放在 RS 正则表达式中,您可以跳过有关使用 iconv
或 dos2unix
或更改 locale
设置的所有步骤 ::
RS
——>ORS
会无缝处理
这样原始输入文件将保持完整,以防您以后出于某种原因需要这些 CR。