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
的选项使put
Miller 将所有记录视为字符串,无论它们是数字还是字符串。
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
将添加到第二个字段。尾随单独的输出1
是awk
(可能已修改的)记录。
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,
。
编辑器中的等效编辑命令ed
是g/^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
每一行,您:
split
在,
逗号上,- 如果第一个元素是“A”的字符串,则运行连接
00
到第二个元素末尾的条件,然后[1]
[0]
eq
- 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 => ","
为适合您的输入文件的分隔符,例如\t
TSV 文件。示例输出与上面相同。