文本处理 - 替换每行从开头算起的第二个和从结尾算起的第二个

文本处理 - 替换每行从开头算起的第二个和从结尾算起的第二个

我的 csv 文件有问题,需要添加一些引号

field,field2,text field with potential commas,field4,field5
field,field2,text fie,ld with pot,ential commas,field4,field5
field,field2,text field with, potential commas,field4,field5

出去

field,field2,"text field with potential commas",field4,field5
field,field2,"text fie,ld with pot,ential commas",field4,field5
field,field2,"text field with, potential commas",field4,field5

sed 's/,/,"/2'将添加第一个引号,但是我如何对每行从末尾向后的第二次出现执行相同的操作?

欢迎使用 sed、awk、perl 等方法。文件有几百万行,速度值得赞赏。

答案1

这是一种awk方法:如果有超过五个逗号分隔字段,则循环遍历连接它们的“中间”字段,然后打印用引号括起来的新字段,然后打印最后两个字段:

awk -f awkscript.awk < input

如下awkscript.awk

BEGIN {
  OFS=","
  FS=","
}
{
        if (NF > 5) {
                middle=""
                for(i=3; i <= NF-2; i++)
                        middle=(middle ? middle"," : "")$i
                print $1, $2, "\""middle"\"", $(NF-1), $NF
        } else {
                print $1, $2, "\""$3"\"", $4, $5
        }
}

答案2

使用sed你会这样做:

sed 's/,/,"/2; s/\(,[^,]*,[^,]*\)$/"\1/' infile

s/,/,"/2仅取代第二个。这从行尾作为与反向引用的组匹配s/\(,[^,]*,[^,]*\)$进行匹配,然后在添加引号后的替换部分中我们将其带回,anything-not-a-comma,anything-not-a-comma$\1"\1

答案3

这是一个非常简单的方法,尽管可能不是最有效的:

sed 's/,/,"/2' input.csv | rev | sed 's/,/,"/2' | rev > output.csv

答案4

sed -e '
   s/,/&\n/2
   s/\n\(.*\)\(,.*,.*\)/"\1"\2/
'    input.csv


 perl -pe '
    my $p;
    while ( /,/g ) {
       s/\G/"/,next if ++$p == 2;

       last if s/,\G(?=.*,)(?!.*,.*,)/",/;  # looks for 2nd last comma
    }
 '    input-file.csv



 perl -pe '
      substr($_, index($_, q/,/, 1+index($_, q/,/)), 1) = q/,"/;

      substr($_, rindex($_, q/,/, -1+rindex($_, q/,/)), 1) = q/",/;
 '     csvfile

这里我们调用索引函数两次来获取左侧第二个逗号的位置。现在位置已经确定,然后使用 substr 函数在其旁边放置一个引号。

同样,我们调用rindex函数并进行相应的更改。

相关内容