我有一个包含5列的长csv文件。但是3行有6列。一个开始于" tomasluck",另一个" peterblack"最后一个" susanpeeters"。我需要在这3行中删除第四个元素(列)并且只获得5列。
我举了一个简短的例子,我的文件很长,是自动创建的。
petergreat, 15, 11-03-2015, 10, 10
tomasluck, 15, 10-03-2015, tl, 10, 10
anaperez, 14, 11-03-2015, 10, 11
我需要
petergreat, 15, 11-03-2015, 10, 10
tomasluck, 15, 10-03-2015, 10, 10
anaperez, 14, 11-03-2015, 10, 11
确切地说,我正在思考一个代码,选择以tomasluck,peterblack和susanpeeters开头的行,然后删除4rht字段或colum。
答案 0 :(得分:2)
关于这一点的棘手问题是保持格式不变。我认为最简单的方法是将输入视为纯文本并使用sed:
sed '/^tomasluck,/ s/,[^,]*//3' file.csv
这将在以tomasluck,
开头的行中删除第三次出现的逗号后跟字段(非逗号字符)。可以修改过滤器正则表达式以包括其他第一个字段,例如
sed '/^\(tomasluck\|petergreat\|anaperez\),/ s/,[^,]*//3' file.csv
...但在您的输入数据中,这些行似乎没有第六个字段。
基于字段数删除第四个字段在sed中有点棘手,主要是因为sed没有算术功能并且识别这些行有点乏味:
sed 'h; s/[^,]//g; /.\{5\}/ { x; s/,[^,]*//3; x; }; x' file.csv
那是:
h # copy the line to the hold buffer
s/[^,]//g # remove all non-comma characters
/.\{5\}/ { # if five characters remain (if the line has six or more
# fields)
x # exchange pattern space and hold buffer
s/,[^,]*//3 # remove field
x # swap back again
}
x # finally, swap in the actual data before printing.
x
舞是典型的使用保持缓冲区的sed脚本;目标是确保无论替换是否发生,最后都会打印出行(而不是孤立的逗号)。
请注意,如果您希望选择条件是一行有六个或更多字段,则值得考虑使用awk,其中条件更容易制定但是更换字段更繁琐:
awk -F , 'BEGIN { OFS = FS } NF > 5 { for(i = 5; i <= NF; ++i) { $(i - 1) = $i }; --NF; $1 = $1 } 1' file.csv
即:用逗号分隔行(-F ,
),然后
BEGIN { OFS = FS } # output field separator is input FS
NF > 5 { # if there are more than five fields
for(i = 5; i <= NF; ++i) { # shift them back one, starting at the fifth
$(i - 1) = $i
}
--NF # let awk know that there is one less field
$1 = $1 # for BSD awk: force rebuilding of the line
}
1 # whether or not a transformation happened, print.
这适用于大多数问题;我用gawk和mawk测试了它。但是,因为没有什么比这更容易移植,我被告知至少有一个awk(在旧的Solaris上,我相信)不理解--NF
技巧。有可能与sprintf
一起破解某些东西,但这已经足够我不希望它咬你了。
答案 1 :(得分:1)
更通用的解决方案是检查我们是否有5个或6个字段:
awk -F', ' '{if(NF==6) print $1", "$2", "$3", "$5", "$6; else print $0}' file.csv
答案 2 :(得分:0)
你可以通过sed使用捕获组基于正则表达式的捕获组来完成此任务。
$ sed 's/^\(\(tomasluck\|peterblack\|susanpeeters\),[^,]*,[^,]*\),[^,]*/\1/' file
petergreat, 15, 11-03-2015, 10, 10
tomasluck, 15, 10-03-2015, 10, 10
anaperez, 14, 11-03-2015, 10, 11
这会捕获第三列之前的所有字符并匹配第四列。用匹配组1中的字符替换匹配的字符将为您提供所需的输出。