将TSV转换为CSV,其中TSV字段中包含逗号

时间:2019-05-28 12:15:35

标签: sed

我有一个TSV,其中的字段如下:

name   location   1,2,3,4,5

当我使用sed 's/\w/,/g'时 我最终得到一个csv,其中1,2,3,4和5被认为是单独的条目。 我希望它是'1 2 3 4 5' 我尝试使用逗号运行上述命令之前将逗号转换为空格

sed 's/,/\w/g' 

但是,当将空格转换回逗号时,它包括单个空格以及制表符,那么单个空格字符的正则表达式是什么?

所需的输出:

name, location,1 2 3 4 5,

4 个答案:

答案 0 :(得分:1)

正如评论中提到的那样,CSV通常通过将值括在引号中来处理其分隔符出现在值中的情况,因此我建议您通过将每个值都括在引号中来解决此问题:

sed -E 's/([^\t]*)(\t|$)/"\1",/g'

您可以try it here

这会在示例输出中留下逗号结尾,如果要避免它,可以使用以下命令:

sed -E 's/\t+$//;s/^/"/;s/\t/","/g;s/$/"/'

如果您的原始数据包含",则需要转义这些数据,您可以通过在其他数据之前添加以下替换来实现:

s/"/\\"/g

正如Ed Morton所建议的那样,我们还可以剥离尾随的空白字段:

s/\t+$//

最后,我将使用以下内容:

sed -E 's/"/\\"/g;s/\t+$//;s/^/"/;s/\t/","/g;s/$/"/'

您可以尝试here

答案 1 :(得分:1)

要么用","替换制表符,并用双引号引起来,要么用空格替换逗号,用逗号将制表符替换。在这两种情况下,您都会获得有效的CSV。

$ cat file
name    location        1,2,3,4,5
$
$ sed 's/\t/","/g; s/^\|$/"/g' file
"name","location","1,2,3,4,5"
$
$ sed 's/,/ /g; s/\t/,/g' file
name,location,1 2 3 4 5

答案 2 :(得分:1)

在awk中:

$ awk -v OFS="," '{for(i=1;i<=NF;i++)if($i~/,/)$i="\"" $i "\"";$1=$1}1' file
name,location,"1,2,3,4,5"

解释:

$ awk -v OFS="," '{          # output delimiter to a comma *
    for(i=1;i<=NF;i++)       # loop all fields
        if($i~/,/)           # if comma in field
            $i="\"" $i "\""  # surround with quotes **
    $1=$1                    # rebuild record
}1' file                     # output

*如果记录中有空格,请考虑使用awk -F"\t"将选项卡的输入字段分隔符。

**,如果字段中用引号引起来,则应该将它们重复或转义。

答案 3 :(得分:0)

根据您的实际需求:

$ awk -F'\t' -v OFS=',' '{for (i=1;i<=NF;i++) $i="\""$i"\""} 1' file
"name","location","1,2,3,4,5"

$ awk -F'\t' -v OFS=',' '{for (i=1;i<=NF;i++) gsub(OFS," ",$i); $1=$1} 1' file
name,location,1 2 3 4 5

$ awk -F'\t' -v OFS=',' '{for (i=1;i<=NF;i++) gsub(OFS," ",$i); $(NF+1)=""} 1' file
name,location,1 2 3 4 5,

$ echo 'a"b' | awk -F'\t' -v OFS=',' '{for (i=1;i<=NF;i++) { gsub(/"/,"\"\"",$i); $i="\""$i"\"" } } 1'
"a""b"