2016-12-26 89 views
3

我有几百万的记录,像下面如何删除多个逗号,但在csv文件中的两个值之间保留一个逗号?

1,,,,,,,,,,a,,,,,,,,,,,,,,,,4,,,,,,,,,,,,,,,456,,,,,,,,,,,,,,,,,,,,,3455,,,,,,,,,, 
1,,,,,,,,,,b,,,,,,,,,,,,,,,,5,,,,,,,,,,,,,,,467,,,,,,,,,,,,,,,,,,,,,3445,,,,,,,,,, 
2,,,,,,,,,,c,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,567,,,,,,,,,,,,,,,,,,,,,4656,,,,,,,,,, 

我必须删除两个值之间的额外逗号,只保留一个CSV文件。对样品的输入输出应该看起来像

1,a,4,456,3455 
1,b,5,467,3445 
2,c,6,567,4656 

我怎样才能做到这一点使用shell,因为它可以自动为其他文件了。 我需要将这些数据加载到数据库中。我们可以用R来做吗?

+2

'awk -F',*''BEGIN {OFS =“,”}; {print $ 1,$ 2,$ 3,$ 4,$ 5}'文件' – Cyrus

+0

@Cyrus很好!应该得到正确的答案。 –

+0

@ Jean-FrançoisFabre:这只有在列数已知的情况下才有效。 – Cyrus

回答

4

sed方法:

sed -e "s/,\+/,/g" -e "s/,$//" input_file > output_file 

打开多个逗号单逗号,并且还取消对线最后一个逗号。

+0

这工作。谢谢。 –

4

编辑以解决修改后的问题。

R解决方案。

提供的原始解决方案只是处理文本。假设你的行是在结构中,你可以处理多行用:

# Create Data 
Row1 = "1,,,,,,,a,,,,,,,,,,4,,,,,,,,,456,,,,,,,,,,,3455,,,,,,," 
Row2 = "2,,,,,,,b,,,,,,,,,,5,,,,,,,,,567,,,,,,,,,,,4566,,,,,,," 
Rows = c(Row1, Row2) 

CleanedRows = gsub(",+", ",", Rows)   # Compress multiple commas 
CleanedRows = sub(",\\s*$", "", CleanedRows) # Remove final comma if any 
[1] "1,a,4,456,3455" "2,b,5,567,4566" 

但是,如果你正试图从一个CSV阅读并压缩行,

## Create sample data 
Data =read.csv(text="1,,,,,,,a,,,,,,,,,,4,,,,,,,,,456,,,,,,,,,,,3455,,,,,,, 
2,,,,,,,b,,,,,,,,,,5,,,,,,,,,567,,,,,,,,,,,4566,,,,,,,", 
header=FALSE) 

你的代码大概会说 Data = read.csv("YourFile.csv", header=FALSE)

Data = Data[which(!is.na(Data[1,]))] 
Data 
    V1 V8 V18 V27 V38 
1 1 a 4 456 3455 
2 2 b 5 567 4566 

注意:这假定非空白字段在日每行中的相同位置。

+0

我们是否需要使用R逐行进行? –

+0

使用'readLines'和'gsub'代码清除额外的逗号可能会更快/更简单,然后才解析剩余的数据帧。 – Gregor

0

如果你有一个真正的CSV文件,它可能会以几种不同的方式引用逗号,这可能会导致基于正则表达式的CSV解析不愉快。

我一般使用并推荐csvkit,它有一套很好的shell解析工具。 Docs at http://csvkit.readthedocs.io/en/latest/

您确切的问题是在csvkit中用这组命令来回答的。首先,csvstat显示文件的样子:

$ csvstat -H --max tmp.csv | grep -v None 1. column1: 2 11. column11: c 27. column27: 6 42. column42: 567 63. column63: 4656

那么,现在你知道所有的数据都在这些栏,就可以运行这个命令:

$ csvcut -c 1,11,27,42,63 tmp.csv 1,a,4,456,3455 1,b,5,467,3445 2,c,6,567,4656

到得到你想要的答案。

+0

谢谢vielmetti –

2

使用tr -s

echo 'a,,,,,,,,b,,,,,,,,,,c' | tr -s ',' 

输出:

a,b,c 

如果输入线已经尾随逗号,tr -s ','会挤压那些尾随逗号为一个逗号,但要摆脱一个需要添加很少sed代码:tr -s ',' | sed 's/,$//'


速度。在包含OP示例中第一行的10,000,000行测试文件上进行测试,重复测试。

  1. 3秒tr -s ','(但留下了尾随逗号)
  2. 9秒tr -s ',' | sed 's/,$//
  3. 30秒sed -e "s/,\+/,/g" -e "s/,$//"Jean-François Fabre's answer。)
+1

'echo'a ,,,,,,,, b ,,,,,,,,,, c,'| tr -s','最后留下一个逗号。 –

+0

@ Jean-FrançoisFabre,不错,它确实无法删除最后一个逗号。追加'| sed's /,$ //''(如你自己的回答)会修正那个... – agc

+0

'tr'通常比别人更好,因为它更简单。在那种情况下,无论如何你必须运行'sed'。但现在你的答案至少是正确的。 –

0

我们能做到这一点,使用R?

提供您的输入如图所示,也就是说,你想跳过所有行同列,可以分析第一线,然后定义列班read.table

text <- "1,,,,,,,,,,a,,,,,,,,,,,,,,,,4,,,,,,,,,,,,,,,456,,,,,,,,,,,,,,,,,,,,,3455,,,,,,,,,, 
     1,,,,,,,,,,b,,,,,,,,,,,,,,,,5,,,,,,,,,,,,,,,467,,,,,,,,,,,,,,,,,,,,,3445,,,,,,,,,, 
     2,,,,,,,,,,c,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,567,,,,,,,,,,,,,,,,,,,,,4656,,,,,,,,,," 

tmp <- read.table(text = text, nrows = 1, sep = ",") 
colClasses <- sapply(tmp, class) 
colClasses[is.na(unlist(tmp))] <- "NULL" 

在这里,我承担第一行没有实际的NA值。如果可能的话,你需要稍微调整它。

read.table(text = text, sep = ",", colClasses = colClasses) 
# V1 V11 V27 V42 V63 
#1 1 a 4 456 3455 
#2 1 b 5 467 3445 
#3 2 c 6 567 4656 

很显然,你指定的file代替text

该解决方案对于中小尺寸数据非常有效。对于大数据,将第二个read.table替换为来自软件包data.table的fread(但适用于不管跳过列的问题)。