在以下文件中,我希望将所有;
替换为,
,不同之处在于,当有一个字符串(以两个"
分隔)时,不应替换;
。
示例: 输入
A;B;C;D
5cc0714b9b69581f14f6427f;5cc0714b9b69581f14f6428e;1;"5cc0714b9b69581f14f6427f;16a4fba8d13";xpto;
5cc0723b9b69581f14f64285;5cc0723b9b69581f14f64294;2;"5cc0723b9b69581f14f64285;16a4fbe3855";xpto;
5cc072579b69581f14f6428a;5cc072579b69581f14f64299;3;"5cc072579b69581f14f6428a;16a4fbea632";xpto;
输出
A,B,C,D
5cc0714b9b69581f14f6427f,5cc0714b9b69581f14f6428e,1,"5cc0714b9b69581f14f6427f;16a4fba8d13",xpto,
5cc0723b9b69581f14f64285,5cc0723b9b69581f14f64294,2,"5cc0723b9b69581f14f64285;16a4fbe3855",xpto,
5cc072579b69581f14f6428a,5cc072579b69581f14f64299,3,"5cc072579b69581f14f6428a;16a4fbea632",xpto,
对于sed,我有:sed 's/;/,/g' input.txt > output.txt
,但这将取代所有内容。
"
分隔字符串的正则表达式:\".*;.*\"
。
(十六进制的正则表达式会更好-类似于:[0-9a-fA-F]+
)
我的问题是将所有内容组合在一起,以制作一个grep -o / sed替换该模式以外的所有内容。
文件大小约为两位数Gb(最大99Gb),因此performance is important. Relevant。
任何想法都值得赞赏。
答案 0 :(得分:1)
sed
用于对单个字符串执行简单的s/old/new
。 grep
用于执行g/re/p
。您没有尝试执行这些任务中的任何一个,因此您不应该考虑这些工具中的任何一个。剩下另一个用于处理文本的标准UNIX工具-awk
。
您有一个用;
分隔的,
分隔的CSV。就是这样:
$ awk -v FPAT='[^;]*|"[^"]+"' -v OFS=',' '{$1=$1}1' file
A,B,C,D
5cc0714b9b69581f14f6427f,5cc0714b9b69581f14f6428e,1,"5cc0714b9b69581f14f6427f;16a4fba8d13",xpto,
5cc0723b9b69581f14f64285,5cc0723b9b69581f14f64294,2,"5cc0723b9b69581f14f64285;16a4fbe3855",xpto,
5cc072579b69581f14f6428a,5cc072579b69581f14f64299,3,"5cc072579b69581f14f6428a;16a4fbea632",xpto,
以上将GNU awk用于FPAT。有关使用awk解析CSV的更多详细信息,请参见What's the most robust way to efficiently parse CSV using awk?。
答案 1 :(得分:0)
如果我正确地满足了您的要求,一种选择就是制作三关。
根据您对十六进制的评论,我认为输入中不会出现#号,因此您可以这样做(使用GNU sed):
sed -E 's/("[^"]+);([^"]+")/\1#\2/g' original > transformed
sed -i 's/;/,/g' transformed
sed -i 's/#/;/g' transformed
这个想法是用引号将;
替换为其他内容并将其写入新文件,然后将所有;
替换为,
,然后退回{{1 }}放在同一文件中(sed的;
标志)。
可以通过以下命令将三遍组合为一个命令
-i
也就是说,可能有很多csv解析器巫婆已经处理了引号字段,您可能会在最终用例中使用该字段,因为我敢打赌,这只是链中其他内容的中间步骤。
根据Ed Morton的评论:如果您一次性完成,可以使用sed -E 's/("[^"]+);([^"]+")/\1#\2/g;s/;/,/g;s/#/;/g' original > transformed
作为替换分隔符,因为在逐行考虑的文本中没有换行符。>
答案 2 :(得分:0)
这可能对您有用(GNU sed):
sed -E ':a;s/^([^"]*("[^"]*"[^"]*)*"[^";]*);/\1\n/;ta;y/;/,/;y/\n/;/' file
用换行符替换;
内的双引号,将;
换成,
,然后将换行符换成;
。