我在HDFS中有一个csv文件,我使用fread()来读入R.数据看起来像这样:
Date Code Value TransactionID
2016-01-01 769 123 16U11863C2MS0000337625C1
2016-02-01 2MS-US 456 16U11863C2MS0000337626C1
2016-03-01 E9E-US 789 16U11863C2MS0000337627C1
我想使用sed
只读取代码" 2MS-US"或" 769"。我没有使用grep
,因为它没有保留标头。我试过了:
fread("hadoop fs -text /path/to/file.csv | sed -n '1p;/^[0-9]*-[0-9]*-[0-9]* 2MS-US/p; /^[0-9]*-[0-9]*-[0-9]* 769/p'", fill=TRUE)
但这会返回零行。我猜我有错误的正则表达式,但不知道如何解决这个问题。
我也尝试过使用awk
,但是在使用条件过滤时没有任何运气:
fread("hadoop fs -text /path/to/file.csv | awk '$2 == 2MS-US'", fill=TRUE)
返回以下错误消息:
fread(....)出错 期望2个cols,但是5293行包含处理完所有cols后的文本。再次尝试使用fill = TRUE。
对sed
或awk
(如果awk
将能够保留标题)的修补方案的任何建议都将非常感谢!
编辑:
感谢@ amaurea以及thread的帮助,我已通过以下代码实现了我的目标:
fread("/usr/bin/hadoop fs -text /path/to/file.csv | awk -F '\"*,\"*' 'FNR==1||$2==\"2MS-US\"||$2==\"769\"'"
如果我错了,请纠正我,但在我看来,当使用awk
处理csv文件时,需要-F '\"*,\"*'
,而文本文件不是这种情况。
答案 0 :(得分:1)
您的awk
脚本中的引用似乎存在问题。需要引用2MS-US
。这个awk命令对我有用:
awk 'FNR==1||$2=="2MS-US"||$2=="769"' hdfs.txt
其中hdfs.txt是包含示例内容的文件。这输出
Date Code Value TransactionID
2016-01-01 769 123 16U11863C2MS0000337625C1
2016-02-01 2MS-US 456 16U11863C2MS0000337626C1
我认为这就是你想要的。但是,由于您在引用的字符串中调用awk,您可能需要转义awk命令中的双引号以避免与fread
中的双引号冲突,如下所示:
fread("hadoop fs -text /path/to/file.csv | awk 'FNR==1||$2==\"2MS-US\"||$2==\"769\"'", fill=TRUE)
虽然确实如此,但人们会期望直接在R中过滤表格会更清晰。
编辑:由于您仍然遇到问题,这里有一个适合我的小测试用例,您可以直接在终端中运行:
$ cat <<HERE > hdfs.txt
Date Code Value TransactionID
2016-01-01 769 123 16U11863C2MS0000337625C1
2016-02-01 2MS-US 456 16U11863C2MS0000337626C1
2016-03-01 E9E-US 789 16U11863C2MS0000337627C1
HERE
$ cat <<HERE > test.r
library(data.table)
fread("awk 'FNR==1||$2==\"2MS-US\"||$2==\"769\"' hdfs.txt")
$ R -q -f test.r
> library(data.table)
> fread("awk 'FNR==1||$2==\"2MS-US\"||$2==\"769\"' hdfs.txt")
Date Code Value TransactionID
1: 2016-01-01 769 123 16U11863C2MS0000337625C1
2: 2016-02-01 2MS-US 456 16U11863C2MS0000337626C1
>