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

时间:2015-03-05 13:30:14

标签: awk

我使用以下脚本查找mongodb-server上正在运行的连接数。

mongostat | awk 'BEGIN{FS=" *"}{print "Number of connections: "$19}'

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

我想修改我的脚本,只有当$19是整数时才能打印。

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

3 个答案:

答案 0 :(得分:17)

使用

mongostat | awk -F ' *' '$19 ~ /^[0-9]+$/ { print "Number of connections: " $19 }'

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

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

mongostat | awk '$19 ~ /^[0-9]+$/ { print "Number of connections: " $19 }'

应该可以正常工作。

答案 1 :(得分:8)

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

$19~/^[0-9]+$/

^代表字符串的开头,$代表结尾,所以我们检查它是否包含从开头到结尾的数字。使用+,我们将其匹配至少一个数字,否则空字段也将匹配(因此具有较少字段的文件将始终匹配)。

所有在一起:

mongostat | awk 'BEGIN{FS=" *"} $19~/^[0-9]+$/ {print "Number of connections: "$19}'

答案 2 :(得分:4)

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

  • 整数有一个符号,因此您在测试中需要考虑到这一点。因此整数-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
}

输出:

+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

如您所见,最后一种情况失败了,因为“%.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)
    }
}

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


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

来源:Awk Posix standard