检查字段是否为awk中的整数

Che*_*eku 10 awk

我使用以下脚本来查找我的mongodb服务器上正在运行的连接数.

mongostat | awk 'BEGIN{FS=" *"}{print "Number of connections: "$19}'
Run Code Online (Sandbox Code Playgroud)

但每10行,$ 19带有一个字符串,表示字段名称.

我想修改我的脚本只有在$19是整数时打印.

我可以尝试FS = " *[^0-9]*",但它匹配以数字开头而不是选择性打印的列.

Win*_*ute 18

使用

mongostat | awk -F ' *' '$19 ~ /^[0-9]+$/ { print "Number of connections: " $19 }'
Run Code Online (Sandbox Code Playgroud)

$19 ~ /^[0-9]+$/检查是否$19与正则表达式匹配^[0-9]+$(即,如果它只包含数字),并且只有在这种情况下才执行相关的操作.

顺便说一下,想到它,特殊的字段分隔符可能是不必要的.默认字段分隔符awk是任何空格序列,因此除非mongostat使用奇怪的制表符和空格组合,

mongostat | awk '$19 ~ /^[0-9]+$/ { print "Number of connections: " $19 }'
Run Code Online (Sandbox Code Playgroud)

应该工作正常.


fed*_*qui 8

检查此字段是否仅由数字组成,使其与正则表达式匹配^[0-9]+$:

$19~/^[0-9]+$/
Run Code Online (Sandbox Code Playgroud)

^代表字符串的开头和$结尾,所以我们检查它是否包含从开头到结尾的数字.随着+我们让它至少匹配一个数字,否则空场也将匹配(这样用更少的字段的文件总是匹配).

全部一起:

mongostat | awk 'BEGIN{FS=" *"} $19~/^[0-9]+$/ {print "Number of connections: "$19}'
Run Code Online (Sandbox Code Playgroud)


kva*_*our 6

在这里你必须非常小心。答案并不像你想象的那么简单:

  • 整数有一个符号,因此您需要在测试中考虑到这一点。所以整数-123+123不会在早期提议的测试中被识别为整数。
  • awk 灵活地将变量类型从浮点数(数字)转换为字符串,反之亦然。转换为字符串是使用sprintf. 如果浮点数表示整数,则使用格式,%d否则使用格式CONVFMT(默认%.6g)。一些更详细的解释在这篇文章的底部。因此,检查数字是否为整数或字符串是否为整数是两件不同的事情。

因此,当您使用正则表达式来测试数字是否为整数时,如果您的变量仍被视为字符串(例如未处理的字段),它将完美无缺地工作。但是,如果您的变量是一个数字,awk 将在进行正则表达式测试之前首先将数字转换为字符串,因此,这可能会失败:

is_integer(x) { x ~ /^[-+]?[0-9]+$/ }
BEGIN { n=split("+0 -123 +123.0 1.0000001",a)
        for(i=1;i<=n;++i) print a[i],is_integer(a[i]), is_integer(a[i]+0), a[i]+0
}
Run Code Online (Sandbox Code Playgroud)

输出:

+0          1          1        0
-123        1          1        -123
+123.0      0          1        123        << QUESTIONABLE
1.0000001   0          1        1          << FAIL
            ^          ^
          test        test
        as string   as number
Run Code Online (Sandbox Code Playgroud)

如您所见,最后一种情况失败了,因为 "%.6g" 转换1.0000001为字符串1,这是因为我们使用字符串操作。

验证变量是否表示整数的更通用的解决方案如下:

function is_number(x)   { return x+0 == x }
function is_string(x)   { return ! is_number(x) }
function is_float(x)    { return x+0 == x && int(x) != x } 
function is_integer(x)  { return x+0 == x && int(x) == x } 
BEGIN { n=split( "0 +0 -0 123 +123 -123 0.0 +0.0 -0.0 123.0 +123.0 -123.0  1.23 1.0000001 -1.23E01 123ABD STRING",a)
    for(i=1;i<=n;++i) {
        print a[i], is_number(a[i]), is_float(a[i]), is_integer(a[i]), \
              a[i]+0, is_number(a[i]+0), is_float(a[i]+0), is_integer(a[i]+0)
    }
}
Run Code Online (Sandbox Code Playgroud)

这种方法在识别123.0为浮点数方面仍然存在问题,但那是因为 awk 只知道浮点数。


与整数值完全相等的数值(请参阅从 ISO C 标准派生的概念)应通过等效于以sprintf字符串"%d"作为fmt参数调用函数(请参阅字符串函数)将其转换为字符串,并且被转换为第一个也是唯一一个expr参数的数值。任何其他数值都应通过等效于以sprintf变量值CONVFMT作为fmt参数调用函数并将数字值转换为第一个也是唯一的expr参数来转换为字符串。如果值为CONVFMT不是浮点格式规范。这卷 POSIX.1-2017 没有指定数字和字符串之间的显式转换。应用程序可以通过向其添加零来强制将表达式视为数字,或者可以通过将空字符串 ( "")连接到它来强制将其视为字符串。

来源:Awk Posix 标准

  • 这些“更通用的解决方案”s/b 被接受的答案(我知道它是在 OP 和最初接受的结果很久之后发布的——只是想引起人们的注意,作为未来访问者更好的解决方案)。 (3认同)