我想从 CSV 文件中过滤出记录,其中postal_code
字段具有浮点值,并且我还希望输出中包含标题。
示例 CSV 文件如下:
> ca test.csv
employee_id|postal_code
1|56024.4
1|752066
预期输出是:
employee_id|postal_code
1|752066
我尝试过的:
> awk '$2 != "." {print $0} ' test.csv
1|56024.4
1|752066
答案1
您的awk
命令测试第二个空格分隔字段是否是点。由于您没有第二个空格分隔的字段,因此它会输出文件中的所有内容。
使用磨坊主( )从输出中mlr
过滤掉包含点的字段的记录(即包括标题):postal_code
ca
$ mlr --csv --fs pipe filter -S '$postal_code !=~ "[.]"' file
employee_id|postal_code
1|752066
过滤器表达式 ,通过将字段$postal_code !=~ "[.]"
的值postal_code
与正则表达式[.]
(可以替换为\.
)进行匹配来测试字段的值,如果测试成功,将丢弃该记录。
该操作-S
的选项filter
关闭字段的类型推断,因此数据仍然是字符串而不是浮点数。
您还可以使用过滤表达式$postal_code =~ "^[[:digit:]]+$"
来允许postal_code
字段中仅包含数字的记录。您可以通过要求特定位数来使这一点更加严格,例如$postal_code =~ "^[[:digit:]]{6}$"
。
答案2
使用sed
$ sed -E '/[^|]*\|[0-9]+\./s/.*//' input_file
employee_id|postal_code
1|752066
答案3
或者像这样,使用grep
:
$ grep -P '.*\|[0-9]{5,9}$' test.csv
1|752066
编辑:根据OP编辑的问题
$ sed -n -E '1p;2,${/^.+\|[0-9]{5,9}$/p}' test.csv
employee_id|postal_code
1|752066
请注意,您也可以使用纯单内衬做类似的事情,而纯单内衬awk
的可能性已经消失。grep
编辑:添加计时信息
$ time -p ( for i in {1..1000}; do
<command>
done )
将上面的 <command> 替换为
sed -n -E '1p;2,${/^.+\|[0-9]{5,9}$/p}' test.csv > /dev/null
真实 3.10
用户 2.19
系统 0.95awk -F'|' 'NR==1;$2 !~ /[[:punct:]]/' test.csv > /dev/null
真实 3.23
用户 2.19
系统 1.06mlr --csv --fs pipe filter -S '$postal_code !=~ "[.]"' test.csv > /dev/null
真实 16.91
用户 5.08
系统 12.37
答案4
像这样:
$ awk -F'|' 'NR==1;$2 !~ /[[:punct:]]/' file
employee_id|postal_code
1|752066