如果满足条件,则使用 sed 将字符串附加到第二列

如果满足条件,则使用 sed 将字符串附加到第二列

CSV 文件:

A,12345,hello
B,67890,hi
A,123456,yo

A预期输出:如果第一列是:,则应在第二列末尾添加两个零:

A,1234500,hello
B,67890,hi
A,12345600,yo

答案1

如果您的数据是通用 CSV 文件,其中可能包含嵌入逗号、引号和换行符的字段,那么我们需要使用 CSV 感知工具,例如磨坊主( mlr) 进行变换:

$ mlr --csv -N put -S '$1 == "A" { $2 .= "00" }' file
A,1234500,hello
B,67890,hi
A,12345600,yo

这会将您的数据读取为无标头 CSV 记录,并添加00到第二个字段的值的末尾(如果第一个字段的值为 )A。子命令-S的选项使putMiller 将所有记录视为字符串,无论它们是数字还是字符串。

Miller 可以使用其选项进行就地编辑-I


如果您的数据位于无标头简单的CSV 格式,这意味着它不包含嵌入逗号、引号或换行符的字段(在 CSV 中需要特殊引用的内容),您可以使用它awk来进行转换:

$ awk -F , 'BEGIN { OFS=FS } $1 == "A" { $2 = $2 "00" }; 1' file
A,1234500,hello
B,67890,hi
A,12345600,yo

在这里,逗号分隔的字段由awk;读取。如果第一个字段是A,则字符串00将添加到第二个字段。尾随单独的输出1awk(可能已修改的)记录。


sed并不真正适合以方便或易于维护的方式编辑结构化文档。如果您的数据位于无标头简单的CSV 形式,您可能可以通过匹配以 string 开头的行A,,并在这些行上第二次出现逗号之前插入两个零:

$ sed '/^A,/ s/,/00,/2' file
A,1234500,hello
B,67890,hi
A,12345600,yo

...但请注意,它sed没有记录或字段的概念,并将每个输入行视为通用文本字符串。

sed上面的表达式中,/^A,/地址由后续替换命令使用,这意味着该s命令将应用于与该正则表达式匹配的所有行(以字符串 开头的行A,)。替换匹配第二由于2表达式末尾的 ,所以在该行上添加逗号,并将其替换为字符串00,

编辑器中的等效编辑命令edg/^A,/ s/,/00,/2(“将以下替换应用于与此正则表达式匹配的所有行”)。vi如果它理解2表达式末尾的 the (但它不理解),这也会起作用。

答案2

使用 Raku(以前称为 Perl_6)

~$ raku -ne 'my @a = .split(",");  \
             if @a[0] eq "A" {@a.[1] ~= "00"};  \
             .put for @a.join(",");'   file

上面的代码只能用于简单的-CSV,即没有需要转义/引用的特殊字符(例如嵌入逗号、嵌入双引号、嵌入换行符)。基本上对于-ne每一行,您:

  1. split,逗号上,
  2. 如果第一个元素是“A”的字符串,则运行连接00到第二个元素末尾的条件,然后[1][0]eq
  3. out 的put元素join用逗号重新组合在一起。

输入示例:

A,12345,hello
B,67890,hi
A,123456,yo

示例输出:

A,1234500,hello
B,67890,hi
A,12345600,yo

如果您有更复杂的 CSV,或者您只是想要一个更强大的解决方案,请使用 Raku 的Text::CSV模块:

~$ raku -MText::CSV -e 'my @a = csv( in => $*IN, sep => ",");  \
         for @a -> $a {$a.[1] ~= "00"  if  $a.[0] eq "A"};  \
         csv( in => @a, out => $*OUT);'  file

您可以将分隔符更改sep => ","为适合您的输入文件的分隔符,例如\tTSV 文件。示例输出与上面相同。

https://raku.land/github:Tux/Text::CSV
https://raku.org

相关内容