在特定字符串之间查找并添加引号

在特定字符串之间查找并添加引号

当我使用 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并避免繁琐的转义工作

相关内容