首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >删除假逗号

删除假逗号
EN

Stack Overflow用户
提问于 2014-01-21 17:39:37
回答 4查看 1.3K关注 0票数 4

一个白痴客户正在生成csv文件,但是一个字段有时在(描述字段)中有额外的逗号。

是否有一个整齐的正则表达式来查找这些坏记录,并用其他东西替换额外的逗号。SED命令行就行了。

示例:

代码语言:javascript
运行
复制
A,B,C,This is a description,D,E
F,G,H,This is a description with a comma (,) in it,D,E

我需要一个SED,可以判断有太多的逗号在行和删除额外的逗号从字段4。

我们没有权利告诉愚蠢的客户更改他们的代码。

添加了

我不反对只删除、一个伪逗号而不得不多次运行的解决方案。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-01-22 10:40:50

解决方案1:单行删除,

这是一个SED单线线:

代码语言:javascript
运行
复制
sed -r 's/([^,],[^,],[^,],)(.*)(,.+,.+)/\1'"$(sed -r 's/([^,],[^,],[^,],)(.*)(,.+,.+)/\2/' <<< $myInput | sed 's/,//g')"'\3/' <<< $myInput

无论实际输入是什么,您都必须替换<<< $myInput

当您使用CSV时,您可能必须调整(两者都发生)正则表达式,以便在CSV表的每一行上匹配。

如果前三个和最后两个字段大于一个字符,则将[^,]替换为[^,]*

解释

我们用这个正则表达式

代码语言:javascript
运行
复制
/([^,],[^,],[^,],)(.*)(,.+,.+)/

它为我们捕获字符串的第一部分(F,G,H,)、第二部分(.*)和最后一部分(,D,E)。

第一和第三捕获组将保持不变,而第二捕获组将被替换。

对于替换,我们称sed为第二次(实际上是第三次)时间。首先,我们只捕获第二个组,其次,我们用任何东西替换每个, (只在捕获组中!)。

证明

当然,如果没有不需要的逗号,则不会替换任何内容:

解决方案2:如果您只想指定一个文件**一个文件**,那么整个文件、逐行删除, ##,并且您可以使用的文件的每一行都应该进行替换。

代码语言:javascript
运行
复制
while read line; do sed -r 's/([^,],[^,],[^,],)(.*)(,.+,.+)/\1'"$(sed -r 's/([^,],[^,],[^,],)(.*)(,.+,.+)/\2/' <<< $line | sed 's/,//g')"'\3/' <<< $line; done < input.txt

最后的input.txt是-显然-你的文件。

我只是在上面的while-loop中使用SED-命令,它读取文本的每一行。这是必要的,因为您必须跟踪正在读取的行,因为您在相同的输入上调用sed两次。

解决方案3:整个文件,将" ##中的字段括起来,正如@Łukasz L.在OP的注释中指出的那样,根据描述CSV格式的RFC1480 -文件,最好将包含逗号的字段括在"中。这比其他解决方案更简单:

代码语言:javascript
运行
复制
sed -r 's/([^,],[^,],[^,],)(.*)(,.*,.*)/\1"\2"\3/' input.txt

再一次,我们有三个捕获组。这样我们就可以简单地在"中包装第二个组了!

票数 3
EN

Stack Overflow用户

发布于 2014-01-22 10:53:25

如果列计数是固定的,我们可以尝试用?:裁剪前三列和最后两列,并在行的其余部分(这是描述)中匹配逗号。我有这样的东西:

代码语言:javascript
运行
复制
(?:^(?:[^,]*,){3})(?:(?:[^,]*(,))*[^,]*)(?:(?:,[^,]*){2}$)

[^,]*是字段(没有逗号),因此(?:^(?:[^,]*,){3})将剪切前3列(包括以下逗号)。(?:(?:,[^,]*){2}$)将删除最后2列,包括后缀逗号。(?:(?:[^,]*(,))*[^,]*)与内部匹配。

在JavaScript中,整个表达式返回完整的描述(用逗号)作为第一个匹配,其中的命令作为第二个。它提供了一种可能性,取决于Regex,要么使用espace替换描述(如果引擎给出匹配表达式的范围),要么用替换语法将匹配逗号的(,)表达式作为目标。

我现在没有使用sed运行和测试的可能性,但是这个正则表达式应该非常接近您需要的解决方案。

票数 2
EN

Stack Overflow用户

发布于 2014-01-21 22:14:10

我试图用sed解决这个问题,但是无法在匹配组中执行替换。相反,我成功地使用了一个可以从终端运行的红宝石单衬垫:

代码语言:javascript
运行
复制
cat your_file | ruby -ne '$_.scan(/^(\w+,\w+,\w+,)([^$]+)(,\w,\w)$/).each{|m|puts m[0]+m[1].gsub(",","")+m[2]}'

这假设总是有6列,第4列可能包含逗号。

代码已经用ruby1.8.7、1.9.1和2.1.0进行了测试。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21265304

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档