AWK筛选具有有效数字或为空的行



我尝试使用awk根据给定列是否包含整数、浮点或空字符串来筛选一些行。

我对整数或将它们添加到规则中的方法有问题,但避免添加像2.e这样的奇怪表达式。

输入:
220802,2249,3
220802,2250,37.5
220802,2251,2.e
220802,2252,28
220802,2253,
220802,2254,19.5
220802,2255,3.a
220802,2256,123.25
220802,2257,1.32e-8
220802,2258,N/A
预期输出:
220802,2249,3
220802,2250,37.5
220802,2252,28
220802,2253,
220802,2254,19.5
220802,2256,123.25
220802,2257,1.32e-8

我尝试了这个,但失败了:

awk -F , '$3 ~ /(^$|[0-9]+.?[0-9]+e?[-+]?[0-9]?+)/' INPUT
220802,2250,37.5
220802,2252,28
220802,2253,
220802,2254,19.5
220802,2256,123.25
220802,2257,1.32e-8

也可以试试这个:

awk -F , '$3 ~ /(^$|[0-9]+|[0-9]+.?[0-9]+e?[-+]?[0-9]?+)/'
220802,2249,3
220802,2250,37.5
220802,2251,2.e
220802,2252,28
220802,2253,
220802,2254,19.5
220802,2255,3.a
220802,2256,123.25
220802,2257,1.32e-8

有什么建议可以考虑吗提前感谢!

GNUAWK手册提供了似乎适用于您的Isnumeric。例如,让file.txt内容为

220802,2249,3
220802,2250,37.5
220802,2251,2.e
220802,2252,28
220802,2253,
220802,2254,19.5
220802,2255,3.a
220802,2256,123.25
220802,2257,1.32e-8
220802,2258,N/A

然后

awk 'function isnumeric(x,  f)
{
switch (typeof(x)) {
case "strnum":
case "number":
return 1
case "string":
return (split(x, f, " ") == 1) && (typeof(f[1]) == "strnum")
default:
return 0
}
}
BEGIN{FS=","}length($3)==0||isnumeric($3,arr)' file.txt

给出输出

220802,2249,3
220802,2250,37.5
220802,2252,28
220802,2253,
220802,2254,19.5
220802,2256,123.25
220802,2257,1.32e-8

说明:我使用length(它是内置函数(来检测第三列是否为零长度字符串,并使用从手册复制的isnumeric函数来检测它是否为数字,如果至少满足其中一个条件,则打印行。您可以选择针对某些角落的情况对其进行测试,以检查该函数是否按您的意愿工作。

(在gawk 4.2.1中测试(

检查是否为空很容易。您可以使用$3~/^$/(就像在正则表达式中一样(,但在这种情况下,由于您还将测试字段是否是一个数字,因此它甚至更短为逻辑";而不是";它利用了只有空字符串和等于零的数字(00.0-0等(为假的事实。

为了测试awk是否认为字段(或变量(是一个数字,可以将其与自身加零进行比较。

因此:

awk -F, '$3~/^$/ || ($3+0 == $3)' INPUT

或:

awk -F, '!$3 || ($3+0 == $3)' INPUT

正则表达式不起作用的原因是你没有锚定它。例如,如果有数字,即使它嵌入在不是数字的东西中,[0-9]+也会匹配。

匹配所有有效的数字表示是很容易出错的。

UPDATE 1:尝试计算所有大小数字,包括逗号分隔的财务数字,即使是没有内置大整数和大浮点功能的awks

—( excluding all potential variations for **NaNs** or **INFinities** )
echo '4.0000000000000000000000000000000000000999999999999999999999
9999999999999999999999999999999944444444e506' |
{m,n,g}awk '(_=$-__)<=+_ || 
/^[+-]?([0-9]?[0-9]?[0-9]?((,[0-9][0-9][0-9])
*|[0-9]*))?([.][0-9]*)?([Ee][+-]?[0-9]+)?$/'    
big-float的大小大约是1682.8956160-bits,肯定需要一个特殊的库来正确处理它,因为即使是八倍的精度也远远不够。

=========================================

对于显示的样本:

mawk '$NF <= +$NF' FS=','