Bash 如果行包含的非数值超过特定数量,则删除该行

Bash 如果行包含的非数值超过特定数量,则删除该行,bash,awk,sed,preprocessor,gawk,Bash,Awk,Sed,Preprocessor,Gawk,我有一个大的(2GB)逗号分隔文本文件,其中包含来自传感器的一些数据。有时传感器关闭,没有数据。如果每行中有超过指定数量的无数据或关闭或任何非数字值,我想删除这些行;不包括标题。我只对从第三栏开始数数感兴趣。例如:我的数据如下所示: Tag, Description,2015/01/01,2015/01/01 00:01:00,2015/01/01 00:02:00, 2015/01/01 00:02:00 1827XYZR/KB.SAT,Data from Process Value,2.1,

我有一个大的(2GB)逗号分隔文本文件,其中包含来自传感器的一些数据。有时传感器关闭,没有数据。如果每行中有超过指定数量的
无数据
关闭
任何非数字
值,我想删除这些行;不包括标题。我只对从第三栏开始数数感兴趣。例如:我的数据如下所示:

Tag, Description,2015/01/01,2015/01/01 00:01:00,2015/01/01 00:02:00, 2015/01/01 00:02:00
1827XYZR/KB.SAT,Data from Process Value,2.1,Off,2.7
1871XYZR/KB.RAT,Data from process value,Off,No Data, No Data
1962XYMK/KB.GAT,Data from Process Value,No Data,5,3
1867XYST/KB.FAT,Data from process value,1.05,5.87,7.80
1871XKZR/KB.VAT,Data from process value,No Data,Off,2
这里第一行是标题,我想保持原样。但我希望从第3列开始删除任何列/字段中包含2个或2个以上
无数据
关闭
或任何
非数字
字段的行。换句话说,五个字段中有四个或四个文本字段的行。在本例中,上面的第3行和第6行有2个或2个以上的
No Data
Off
字段,我想删除它们。因此,我的首选输出是

Tag, Description,2015/01/01,2015/01/01 00:01:00,2015/01/01 00:02:00, 2015/01/01 00:02:00
1827XYZR/KB.SAT,Data from Process Value,2.1,Off,2.7
1962XYMK/KB.GAT,Data from Process Value,No Data,5,3
1867XYST/KB.FAT,Data from process value,1.05,5.87,7.80  
我可以在循环的特定情况下执行此操作,如下所示:

awk -F, '{ non_numeric=0;
  for(i=1;i<=NF;i++){
    if($i ~ // ) non_numeric++
  }
  if(non_numeric<2) print $0
}' testfile.txt

它不工作,也没有输出。另外,由于我正在使用loop,我估计它会很慢。我们能不能加快速度。任何命令行解决方案都可以。

惰性方式:打印iff字段3-5至少包含一个数字字符:

awk -F, '$3$4$5 ~ "[0-9]"' data.csv
grep ',[0-9]' data.csv
lazier way(适用于示例数据):print iff行包含逗号,后跟数字字符:

awk -F, '$3$4$5 ~ "[0-9]"' data.csv
grep ',[0-9]' data.csv

惰性方式:打印iff字段3-5至少包含一个数字字符:

awk -F, '$3$4$5 ~ "[0-9]"' data.csv
grep ',[0-9]' data.csv
lazier way(适用于示例数据):print iff行包含逗号,后跟数字字符:

awk -F, '$3$4$5 ~ "[0-9]"' data.csv
grep ',[0-9]' data.csv
awk-F,'
{nonnum=0;
对于(i=3;i=2){next;}
}
}
}1'填充>输出文件
如果循环从未执行,则末尾的
1
将打印该行
next
以跳过当前行的剩余模式。

awk-F,'
{nonnum=0;
对于(i=3;i=2){next;}
}
}
}1'填充>输出文件
如果循环从未执行过,则末尾的
1
将打印该行
next
,以跳过当前行的剩余模式。

使用静态字符串:

$ awk '(a=$0) && gsub(/No Data|Off/,"",a)<2' file
如果要匹配所有非数字字符串,请使用:

awk 'NR==1 || (a=$0) && gsub(/,[^\.,0-9]+/,"",a)<3' file
awk'NR==1 | |(a=$0)和&gsub(/,[^\,0-9]+/,“”,a)带有静态字符串:

$ awk '(a=$0) && gsub(/No Data|Off/,"",a)<2' file
如果要匹配所有非数字字符串,请使用:

awk 'NR==1 || (a=$0) && gsub(/,[^\.,0-9]+/,"",a)<3' file
awk'NR==1 | |(a=$0)和&gsub(/,[^\,0-9]+/,“”,a)这可能适合您(GNU-sed):

使用alternation删除包含2个或更多指定字符串的行。

这可能适用于您(GNU-sed):


使用alternation删除包含2个或更多指定字符串的行。

您可以使用
grep
执行此操作:

grep -vP '((?<=,|^)(No Data|Off)(?=,|$).*){2,}' input

Tag, Description,2015/01/01,2015/01/01 00:01:00,2015/01/01 00:02:00, 2015/01/01 00:02:00
1827XYZR/KB.SAT,Data from Process Value,2.1,Off,2.7
1962XYMK/KB.GAT,Data from Process Value,No Data,5,3
1867XYST/KB.FAT,Data from process value,1.05,5.87,7.80

grep-vP'((?您可以使用
grep
执行此操作:

grep -vP '((?<=,|^)(No Data|Off)(?=,|$).*){2,}' input

Tag, Description,2015/01/01,2015/01/01 00:01:00,2015/01/01 00:02:00, 2015/01/01 00:02:00
1827XYZR/KB.SAT,Data from Process Value,2.1,Off,2.7
1962XYMK/KB.GAT,Data from Process Value,No Data,5,3
1867XYST/KB.FAT,Data from process value,1.05,5.87,7.80

grep-vP'((?有了GNU awk,您可以使用以下物品:

awk 'NF<2' FPAT='No Data' file

awk'NF有了GNU awk,您可以使用以下物品:

awk 'NF<2' FPAT='No Data' file
awk'NF
$perl-F,-ane'print if$.==1 | |(grep{!/\d/}@F[2..$#F])<2'ip.txt
标签,描述,2015/01/012015/01/01 00:01:002015/01/01 00:02:00,2015/01/01 00:02:00
1827XYZR/KB.SAT,来自过程值的数据,2.1,关闭,2.7
1962XYMK/KB.GAT,来自过程值的数据,无数据,5,3
1867XYST/KB.FAT,来自过程值的数据,1.05,5.87,7.80
  • -F,
    上拆分输入行,
  • $。==1
    如果行号为
    1
    ,即打印标题
  • (grep{!/\d/}@F[2..$#F])<2
    如果第3列到末尾的非数字字段数少于两个,则打印。该条件仅检查数字是否不存在
要检查的列和检查的次数可以根据需要轻松更改。例如:
@F[3..$#F]
从第4列开始检查,
<3
检查少于三个的非数字字段的数量

$perl-F,-ane'print if$.==1 | |(grep{./\d/}@F[2..$#F])<2'ip txt
标签,描述,2015/01/012015/01/01 00:01:002015/01/01 00:02:00,2015/01/01 00:02:00
1827XYZR/KB.SAT,来自过程值的数据,2.1,关闭,2.7
1962XYMK/KB.GAT,来自过程值的数据,无数据,5,3
1867XYST/KB.FAT,来自过程值的数据,1.05,5.87,7.80
  • -F,
    上拆分输入行,
  • $。==1
    如果行号为
    1
    ,即打印标题
  • (grep{!/\d/}@F[2..$#F])<2
    如果第3列到末尾的非数字字段数少于两个,则打印。该条件仅检查数字是否不存在

要检查的列和检查的次数可以根据需要轻松更改。例如:
@F[3..$#F]
从第4列开始检查,
<3
检查少于三个的非数字字段的数量

使用
For()
循环以计算数字字段的数量。循环完成后,如果行数至少为4,则打印行数。基本上,我只是重申了您的要求。将其转换为
awk
代码应该很简单。请显示您尝试了什么,以便我们可以帮助您修复。我们不会为您完成工作。示例数据中的第三行包含以下内容:
无数据。无数据
。这是一个打字错误吗?
是否应该是一个
?@Barmar和redneb我已经添加了自己的工作,并修复了数据中的打字错误。很抱歉,不是离散的。它应该是两个或两个以上。我还纠正了这个问题,很抱歉弄乱了。使用
for()
循环以计算数字字段的数量。循环完成后,如果行数至少为4,则打印行数。基本上,我只是重申了您的要求。将其转换为
awk
代码应该很简单。请显示您尝试了什么,以便我们可以帮助您修复。我们不会为您完成工作。示例数据中的第三行包含以下内容:
无数据。无数据
。这是一个打字错误吗?
是否应该是一个
?@Barmar和redneb我已经添加了自己的工作并修复了数据中的打字错误。很抱歉没有被讨论