当我使用 csv 时,不需要的逗号(',')会误导我的 csv 文件,导致不一致。
请在下面详细了解。
我的示例 csv 文件:
1|a,b|4
1|c,d|4
1|e,f|4
1|g,h|4
1|i,j|4
我想要的最终结果为:
1|"a,b"|4
1|"c,d"|4
1|"e,f"|4
1|"g,h"|4
1|"i,j"|4
添加引号后,我将替换“|”与“,”这样我的csv将按我的预期工作。
我使用了下面的命令,但它没有按预期给出。
sed -e 's/,/"&"/' file1.txt
答案1
使用csvformat
来自csvkit
,并假设最终结果应该是一个以逗号作为分隔符的 CSV 文件(如问题文本中所述):
$ csvformat -d '|' file
1,"a,b",4
1,"c,d",4
1,"e,f",4
1,"g,h",4
1,"i,j",4
这会将 CSV 文件的格式从使用|
- 字符作为分隔符重新设置为使用默认逗号作为分隔符。这样做时,它正确地引用了需要引用的字段。
这也可以正确处理带有嵌入换行符的字段:
$ cat file
1|a,b|4
1|c,d|4
1|e,f|4
1|g,h|4
1|i,j|4
2|"line 1,
line2"|5
$ csvformat -d '|' file
1,"a,b",4
1,"c,d",4
1,"e,f",4
1,"g,h",4
1,"i,j",4
2,"line 1,
line2",5
如果您有某种结构化文档格式的文档,例如 CSV、JSON、XML、YAML、TOML 等,则没有理由不是使用该文档格式的解析器来解析该文档。
答案2
你可以这样做:
awk -F'[|]' -v OFS=',' -v q='"' '{ for(i=1; i<=NF; i++) $i=q $i q }1' infile
我们-F'[|]'
定义了输入字段分隔符。
我们-v OFS=','
定义了输出字段分隔符。
NF
根据 FS(输入字段分隔符)确定每行/记录中有多少个字段,因此我们循环遍历字段数并为每个字段添加双引号,并在该行上打印最终更新awk 的1
习惯用法用于打印。
请注意,所有字段都被此命令引用,这显然对于拥有有效的 CSV 文件来说不是问题。
答案3
和sed
:
$ sed 's/[^|]*,[^|]*/"&"/g; y/|/,/' ip.txt
1,"a,b",4
1,"c,d",4
1,"e,f",4
1,"g,h",4
1,"i,j",4
s/[^|]*,[^|]*/"&"/g
向包含以下内容的所有字段添加双引号,
y/|/,/
将所有|
字符更改为,
和perl
:
perl -F'\|' -lane 'print join ",", map {/,/ ? qq("$_") : $_} @F'
这用作|
输入字段分隔符。然后map
将为所有包含 的字段添加双引号,
。最后,join
用于将字段与,
字符组合起来。
答案4
其他sed
方式:
sed 's;\([^|]*\)|\([^|]*\)|\(.*\)$;\1,"\2",\3;' data
或者,如果您sed
支持加载ERE
,例如GNU sed
,您可以避免所有转义作业:
sed -E 's;([^|]+)\|([^|]+)\|(.+)$;\1,"\2",\3;' data
您可以利用这样一个事实,即只有中间组|
在每个边界处由 a 分隔,并使长度变得sed
更短:
sed 's;|\([^|]*\)|;,"\1",;' data
当然也在这里,如果您的 sed 支持,-E
您可以加载ERE
并避免繁琐的转义工作