在第 n 次出现的逗号之前/之后添加引号

在第 n 次出现的逗号之前/之后添加引号

我有一个这种格式的文件:

a1,b1,c1,d1,e1,f1
a2,b2,c2,d2,e2,f2

我想在特定列周围添加引号 (")(例如 a 列和 d 列、列不要包含其他逗号,但它们的长度不同)以获得如下内容:

"a1",b1,c1,"d1",e1,f1
"a2",b2,c2,"d2",e2,f2

我尝试在多次迭代中执行类似下面的操作,将逗号 (,) 替换为逗号+引号 (,") 或引号+逗号 (",),具体取决于它是列的开头还是结尾:

sed -E 's/(([^,]*,){1}[^,]*),/\1\,\"/g'

但这会将每个第二个逗号替换为逗号和引号,而我希望每个命令仅控制一个添加引号的位置。

答案1

首先,您不希望g,这意味着“全局”,替换所有出现的情况,并且由于您需要指定一列,因此您不想替换全部。接下来,您可以sed像这样定位第 N 次出现:s/old/new/N其中N是第 N 次出现。因此,引用第四个字段,您可以这样做:

$ sed 's/[^,]*/"&"/4' file 
a1,b1,c1,"d1",e1,f1
a2,b2,c2,"d2",e2,f2

并更改第一个字段:

$ sed 's/[^,]*/"&"/1' file 
"a1",b1,c1,d1,e1,f1
"a2",b2,c2,d2,e2,f2

&是一个特殊sed变量,表示“运算符左侧匹配的任何内容s///”。

答案2

awk对字段很好用(我自己不太好——这适用于字段 1 和 3,而不是 1 和 4)。

Awk='{
    sub(/.*/, Dq "&" Dq, $1);
    sub(/.*/, Dq "&" Dq, $3);
    print;
}'

$ awk -v FS=, -v OFS=, -v Dq='"' "${Awk}" <<'[][]'
a1,b1,c1,d1,e1,f1
a2,b2,c2,d2,e2,f2
[][]

"a1",b1,"c1",d1,e1,f1
"a2",b2,"c2",d2,e2,f2

答案3

传递要引用的字段列表

awk -v fields='1,4' '
    BEGIN {
        FS = OFS = ","
        n = split(fields, fs)
    }
    { for (i=1; i<=n; i++) $(fs[i]) = "\"" $(fs[i]) "\"" }
    { print }
' file
"a1",b1,c1,"d1",e1,f1
"a2",b2,c2,"d2",e2,f2

答案4

使用awk磨坊主( mlr),您要引用的字段编号在命令行上以逗号分隔的列表形式给出:

$ awk -F, -v f=1,4,5 'BEGIN { OFS=FS; split(f,a,",") } { for (i in a) $a[i] = "\"" $a[i] "\"" };1' file
"a1",b1,c1,"d1","e1",f1
"a2",b2,c2,"d2","e2",f2
$ mlr --nidx --fs comma put -s f=1,4,5 'begin { @a=splitnv(@f,",") } for (k,v in @a) { $[v] = "\"" . $[v] . "\"" }' file
"a1",b1,c1,"d1","e1",f1
"a2",b2,c2,"d2","e2",f2

两者在将输入视为一组逗号分隔记录的“简单 CSV”方面是等效的(没有字段嵌入分隔符或换行符)。

他们分割给定的数字字符串,其中每个数字对应于一个应该引用的字段。然后他们迭代这些字段并通过添加引号来修改每个字段。

相关内容