给定一个数字列文件,称为f,下面的Awk代码将返回最大值
cat f | awk ' BEGIN {max = -inf}
{if ($1>max) max=$1}
END { print max }
'同样的获得最小值的方法不会产生任何结果
cat f | awk '
BEGIN {min = inf}
{if ($1但是,如果我不使用inf,而是从min = [some large number]开始,如果数字足够大,取决于文件中的内容,那么修改后的代码可以工作。
为什么inf不能工作,并且有什么方法可以使min案例像max案例那样工作,而不需要知道文件中有什么?
发布于 2020-05-04 15:09:10
<#>实际<#><#>任务最好通过初始化您的最大值/min值来解决,而不是通过假想的“最小”或“最大”数字来解决(在本例中,这个值可能不是在您正在使用的框架中实现),而是通过使用实际数据来初始化它。这样,它总是保证提供一个有意义的结果。
在您的示例中,您可以使用遇到的第一个值(即第一行中的条目)分别通过添加规则来初始化max和min。
NR==1{min=$1}到您的awk脚本。然后,如果第一个值已经是最小值,那么后续的测试将不会覆盖它,最终将产生正确的结果。对于最大值的搜索也是如此,因此在组合搜索中,可以声明
NR==1{max=min=$1}As是因为您使用 inf <#><#>的方法没有在awk上工作,而-inf似乎在评论您的问题时给出了一个很好的解释,为了完整起见,我也将对此进行总结:
awk中,变量是“动态类型的”,也就是说,根据使用情况,所有变量都可以是字符串或数字(但awk会“记住”上次使用的内容,并将该信息保留在下一次操作中使用)。awk将尝试将该变量的内容解释为一个数字,并执行操作,如果成功,则从该变量中键入数字。inf在awk中没有特殊意义,因此在使用时,它是一个空变量,它将在算术表达式(如-inf )中计算为0。因此,如果数据都是正的,那么初始化为max变量为-inf的“最大搜索”可以工作,因为-inf只是0(因此,最小的非负数)。min初始化为inf将变量初始化为空字符串,因为不存在需要将空字符串自动转换为数字的算术操作。awk也将$1视为字符串,并执行字典比较而不是数字比较。min从未得到新的值。因此,在END部分中,语句prints打印(仍然)空字符串。(*)参见斯蒂芬·凯特的回答中的"inf"内容字符串在awk中的实际意义。
发布于 2020-05-04 15:15:38
您的方法不起作用,因为在GNU中,inf在其默认的非POSIX模式中没有特殊意义。因此,它被解释为变量名,并且由于变量没有被设置为任何内容,它的值在算术上下文中为0,而在字符串上下文中为空字符串。因此,只有当最大值为正(因为max是在算术上下文中初始化的)时,代码才会找到最大值,而不会找到最小值(因为min是在字符串上下文中初始化的);有关详细信息,请参阅行政蜜蜂的回答。
要确定文件(或流)中的最小值和/或最大值,应遵循行政蜜蜂的回答中提供的建议。
但是,如果使用GNU,则可以计算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。)
对于POSIX模式下的GNU (POSIXLY_CORRECT=1)或其他兼容POSIX的AWK解释器(如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}发布于 2020-05-05 21:28:12
实际上,存在三个无穷大的值:-inf +inf和inf,为了增加问题的复杂性,在awk中有引用和未引用的代码常量。
为了说明我的意思,请尝试如下( awk 4.2.1 (当前Debian 10)中的shell代码):
for cmd in original-awk "busybox awk" mawk nawk awk; do
printf '%-6.5s' "$cmd"
$cmd 'BEGIN {
a="-inf";b="+inf";c="inf";
d= -inf ;e= +inf; f= inf;
printf "-∞%4s%4s +∞%4s%4s ∞%4s%4s | -∞%4s%4s +∞%4s%4s ∞%4s%4s\n",a,a+0,b,b+0,c,c+0,d,d+0,e,e+0,f,f+0}
' file得到:
bawk -∞-inf-inf +∞+inf inf ∞ inf inf | -∞ 0 0 +∞ 0 ∞ 0
busyb -∞-inf-inf +∞+inf inf ∞ inf inf | -∞ 0 0 +∞ 0 0 ∞ 0
mawk -∞-inf-inf +∞+inf inf ∞ inf inf | -∞ 0 0 +∞ 0 0 ∞ 0
nawk -∞-inf-inf +∞+inf inf ∞ inf 0 | -∞ 0 0 +∞ 0 0 ∞ 0
gawk -∞-inf-inf +∞+inf inf ∞ inf 0 | -∞ 0 0 +∞ 0 0 ∞ 0该表列出了引用和未引用的变量赋值(abcdef)。对于每一种情况,由awk读取并转换为number (var+0)的值。
这意味着,即使在数字、"-inf"被转换为数字inf (没有符号)时,"inf"仍然保持不变,引用的D8可能会根据实现(在nawk和gawk中为0)变成inf或0。
当没有引号时,-inf和+inf都变成0 (除了在bawk中,+∞被理解为空字符串"“并转换为0)。
奇怪的是,当没有引用时,所有inf都被解释为空字符串。
但所有未引用的-inf、+inf和inf在用作var+0时都变为0。
因此,对于您想要做的事情,您需要引用"-inf"和"+inf",而不是inf:
cat file | awk ' BEGIN { max = "-inf"+0; min = "+inf"+0 }
{ if ($1>max) max=$1
if ($1也许,一种更容易(而不是portable0 )理解它的方法是执行:
gawk 'BEGIN{
a="-inf";b="+inf";c="inf";
d= -inf ;e= +inf; f= inf;
print a, typeof(a), b, typeof(b), c, typeof(c)
print a+0, typeof(a+0), b+0, typeof(b+0), c+0, typeof(c+0)
print d,typeof(d),e,typeof(e),f,typeof(f)
print d+0,typeof(d+0),e+0,typeof(e+0),f+0,typeof(f+0)
}'它将打印:
-inf string +inf string inf string
-inf number inf number 0 number
0 number 0 number unassigned
0 number 0 number 0 number当然,正确和可移植的解决方案是从一开始就给max和min变量赋值:
cat file | awk ' NR==1 { min = max = $1 }
{ if ($1>max) max=$1
if ($1-描述从awk手册上是:
有了--posix命令行选项,gawk就变成了“放手”。字符串值直接传递给系统库的strtod()函数,如果它成功地返回一个数值,则使用该值。根据定义,结果不能跨不同系统移植。它们也有点令人惊讶:$ -| inf $ echo 0xDeadBeef gawk --posix '{打印$1 +0 }‘-| 3735928559
如果没有--posix,gawk将特别解释四个字符串值‘+inf’、‘-inf’、‘+nan’和‘-nan’,从而生成相应的特殊数值。前导符号向gawk (和用户)传递一个信号,表示该值实际上是数字的。不支持十六进制浮点数(除非您也使用--非十进制数据,这是不推荐的)。例如:$ echo nanny gawk '{ print $1 +0 }‘-| 0$ echo +nan gawk '{ print $1 +0 }’-| +nan $ 0xDeadBeef颇具gawk '{ print $1 +0 }‘-| 0 gawk忽略四个特殊值中的大小写。因此,‘+NaN’和‘+NaN’是相同的。除了处理输入,gawk还需要在输出值为NaN或无穷大时打印“正确”值。从4.2.2版本开始,对于这些值,gawk打印了刚才描述的四个字符串中的一个:‘+inf’、‘-inf’、‘+nan’或‘-nan’。类似地,在POSIX模式下,gawk使用值的%g格式字符串打印系统的C printf()函数的结果,不管是什么。
https://unix.stackexchange.com/questions/584421
复制相似问题