我使用以下脚本查找mongodb-server上正在运行的连接数。
mongostat | awk 'BEGIN{FS=" *"}{print "Number of connections: "$19}'
但每10行,$ 19带有一个字符串,表示字段名称。
我想修改我的脚本,只有当$19
是整数时才能打印。
我可以尝试FS = " *[^0-9]*"
,但它会匹配以数字开头而不是选择性打印的列。
答案 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
在较早提出的测试中将不会被识别为整数。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不指定数字和字符串之间的显式转换。应用程序可以通过将表达式加零来强制将其视为数字,也可以通过将空字符串(""
与其连接来强制将其视为字符串。