我想从 csv 文件中删除几行。
规则很简单(如果保持不变):
- 这是文件中的第一行。
- 第一个值与前一行的第一个值不同。
- 第二个值比之前保留的行至少增加了 10。
来源
Test1, 0.0, 1
Test1, 0.2, 1
Test1, 10.0, 3
Test2, 0.1, 1
Test2, 0.3, 3
Test2, 1.0, 5
Test2, 11.0, 7
结果
Test1, 0.0, 1
Test1, 10.0, 3
Test2, 0.1, 1
Test2, 11.0, 7
我正在考虑使用 awk 和一些 if 语句来执行此操作,但我不确定是否可以创建一个在记录处理之间传输的变量。
编辑:这被隐藏在评论部分(来自我):
我刚发现变量在记录之间是可用的。这不像 C 那样有效。除非有人给出我认为对其他人有用的答案,或者有人要求我提供答案,否则我将删除此问题。
答案1
因为它被标记为 awk
awk -F", *" 'x!=$1||$2>=y+10{y=$2;print}{x=$1}' file
Test1, 0.0, 1
Test1, 10.0, 3
Test2, 0.1, 1
Test2, 11.0, 7
答案2
使用 Perl:
perl -lane 'if($.==1||"$F[0]"ne"$F0"||$F[1]>=$F1+10){print;$F1=@F[1]}$F0=@F[0]' file
展开:
if($. == 1 || "$F[0]" ne "$F0" || $F[1] >= $F1 + 10){
print;
$F1 = @F[1]
}
$F0 = @F[0]
if($.==1||"$F[0]"ne"$F0"||$F[1]>=$F1+10){print;$F1=@F[1]}
:若当前行号为1
,当前行第一个字段等于上一行第一个字段或者当前行第二个字段大于或等于上一行第二个字段,则打印当前行并将当前行第二个字段的值赋给F1
;$F0=@F[0]
: 将当前行第一个字段的值赋给F0
;
% cat file
Test1, 0.0, 1
Test1, 0.2, 1
Test1, 10.0, 3
Test2, 0.1, 1
Test2, 0.3, 3
Test2, 1.0, 5
Test2, 11.0, 7
% perl -lane 'if($.==1||"$F[0]"ne"$F0"||$F[1]>=$F1+10){print;$F1=@F[1]}$F0=@F[0]' file
Test1, 0.0, 1
Test1, 10.0, 3
Test2, 0.1, 1
Test2, 11.0, 7
答案3
使用 Python 脚本:
#! /usr/bin/env python3
import sys
with open (sys.argv[1]) as f:
rows=[list(map(str.strip, line.split(','))) for line in f.readlines()]
result=rows[0:1]
for r in rows:
if r[0] != result[-1][0] or float(r[1]) >= float(result[-1][1])+10:
result.append(r)
print("\n".join([",".join(res) for res in result]))
复制上述脚本并将其粘贴到名为的文件中csvfilter.py
。
使用 使其可执行chmod +x csvfilter.py
。
然后,您可以从命令行运行它,并使用要处理的 csv 文件(我将问题中的示例保存为source.csv
)作为参数:
$ ./csvfilter.py source.csv
Test1,0.0,1
Test1,10.0,3
Test2,0.1,1
Test2,11.0,7
该脚本不会修改原始文件,而只是将新版本打印到标准输出。此外,任何以前使用空格的格式都将被丢弃。
要用修改后的版本替换原始文件,请将输出重定向回原始文件:
$ ./csvfilter.py source.csv > source.csv
您还可以将修改后的版本保存为文件:
$ ./csvfilter.py source.csv > modified.csv