检查一个字段是否是awk中的整数
Check if a field is an integer in awk
我正在使用以下脚本查找 mongodb 服务器上的 运行 连接数。
mongostat | awk 'BEGIN{FS=" *"}{print "Number of connections: "}'
但是$19每10行带一个字符串,表示一个字段名。
我想修改脚本以仅在 </code> 为整数时打印。</p>
<p>我可以尝试 <code>FS = " *[^0-9]*"
,但它匹配以数字开头的列,而不是选择性打印。
使用
mongostat | awk -F ' *' ' ~ /^[0-9]+$/ { print "Number of connections: " }'
~ /^[0-9]+$/
检查 </code> 是否与正则表达式 <code>^[0-9]+$
匹配(即,如果它仅由数字组成),并且只有在这种情况下才会执行关联的操作。
顺便说一下,特殊的字段分隔符可能是不必要的。 awk
的默认字段分隔符是任意序列的空格,因此除非 mongostat
使用制表符和空格的奇怪组合,否则
mongostat | awk ' ~ /^[0-9]+$/ { print "Number of connections: " }'
应该可以正常工作。
检查此字段是否仅由数字组成,方法是使其与正则表达式匹配 ^[0-9]+$
:
~/^[0-9]+$/
^
代表字符串的开始,$
代表结束,所以我们检查它是否从开始到结束都是数字。使用 +
我们让它至少匹配一个数字,否则空字段也会匹配(因此字段较少的文件总是会匹配)。
总计:
mongostat | awk 'BEGIN{FS=" *"} ~/^[0-9]+$/ {print "Number of connections: "}'
你在这里必须非常小心。答案并没有你想象的那么简单:
- 整数有符号,所以你需要在测试中考虑到这一点。所以整数
-123
和 +123
在早期提议的测试中不会被识别为整数。
- awk 灵活地将变量类型从浮点数(数字)转换为字符串,反之亦然。转换为字符串是使用
sprintf
完成的。如果浮点数表示整数,则使用 %d
格式,否则使用 CONVFMT
格式(默认 %.6g
)。一些更详细的解释在这个 post 的底部。因此,检查数字是否为整数或字符串是否为整数是两件不同的事情。
所以当你使用正则表达式来测试一个数字是否为整数时,如果你的变量仍然被认为是一个字符串(比如一个未处理的字段),它会完美地工作。但是,如果您的变量是一个数字,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 只知道浮点数。
A numeric value that is exactly equal to the value of an integer (see Concepts Derived from the ISO C Standard) shall be converted to a string by the equivalent of a call to the sprintf
function (see String Functions) with the string "%d"
as the fmt
argument and the numeric value being converted as the first and only expr
argument. Any other numeric value shall be converted to a string by the equivalent of a call to the sprintf
function with the value of the variable CONVFMT
as the fmt
argument and the numeric value being converted as the first and only expr
argument. The result of the conversion is unspecified if the value of CONVFMT
is not a floating-point format specification. This volume of POSIX.1-2017 specifies no explicit conversions between numbers and strings. An application can force an expression to be treated as a number by adding zero to it, or can force it to be treated as a string by concatenating the null string ( ""
) to it.
source: Awk Posix standard
我正在使用以下脚本查找 mongodb 服务器上的 运行 连接数。
mongostat | awk 'BEGIN{FS=" *"}{print "Number of connections: "}'
但是$19每10行带一个字符串,表示一个字段名。
我想修改脚本以仅在 </code> 为整数时打印。</p>
<p>我可以尝试 <code>FS = " *[^0-9]*"
,但它匹配以数字开头的列,而不是选择性打印。
使用
mongostat | awk -F ' *' ' ~ /^[0-9]+$/ { print "Number of connections: " }'
~ /^[0-9]+$/
检查 </code> 是否与正则表达式 <code>^[0-9]+$
匹配(即,如果它仅由数字组成),并且只有在这种情况下才会执行关联的操作。
顺便说一下,特殊的字段分隔符可能是不必要的。 awk
的默认字段分隔符是任意序列的空格,因此除非 mongostat
使用制表符和空格的奇怪组合,否则
mongostat | awk ' ~ /^[0-9]+$/ { print "Number of connections: " }'
应该可以正常工作。
检查此字段是否仅由数字组成,方法是使其与正则表达式匹配 ^[0-9]+$
:
~/^[0-9]+$/
^
代表字符串的开始,$
代表结束,所以我们检查它是否从开始到结束都是数字。使用 +
我们让它至少匹配一个数字,否则空字段也会匹配(因此字段较少的文件总是会匹配)。
总计:
mongostat | awk 'BEGIN{FS=" *"} ~/^[0-9]+$/ {print "Number of connections: "}'
你在这里必须非常小心。答案并没有你想象的那么简单:
- 整数有符号,所以你需要在测试中考虑到这一点。所以整数
-123
和+123
在早期提议的测试中不会被识别为整数。 - awk 灵活地将变量类型从浮点数(数字)转换为字符串,反之亦然。转换为字符串是使用
sprintf
完成的。如果浮点数表示整数,则使用%d
格式,否则使用CONVFMT
格式(默认%.6g
)。一些更详细的解释在这个 post 的底部。因此,检查数字是否为整数或字符串是否为整数是两件不同的事情。
所以当你使用正则表达式来测试一个数字是否为整数时,如果你的变量仍然被认为是一个字符串(比如一个未处理的字段),它会完美地工作。但是,如果您的变量是一个数字,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 只知道浮点数。
A numeric value that is exactly equal to the value of an integer (see Concepts Derived from the ISO C Standard) shall be converted to a string by the equivalent of a call to the
sprintf
function (see String Functions) with the string"%d"
as thefmt
argument and the numeric value being converted as the first and onlyexpr
argument. Any other numeric value shall be converted to a string by the equivalent of a call to thesprintf
function with the value of the variableCONVFMT
as thefmt
argument and the numeric value being converted as the first and onlyexpr
argument. The result of the conversion is unspecified if the value ofCONVFMT
is not a floating-point format specification. This volume of POSIX.1-2017 specifies no explicit conversions between numbers and strings. An application can force an expression to be treated as a number by adding zero to it, or can force it to be treated as a string by concatenating the null string (""
) to it.source: Awk Posix standard