如何从 Unix 命令行将“test10”列截断为 5 个字符?
由此
test1,test2,test3,test4,test10,test11,test12,test17
rh,mbn,ccc,khj,ee3 eeeeeEeee ee$eeee e.eeeee2eeeee5eeeeeeee,a2,3,u
hyt,bb,mb,khj,R ee3ee eeEeee ee$eeee e.eeeee2eeeee5eeeeeeee,a,5,r
mbn,htr,ccc,fdf,F1ee eeeeEeee ee$eeee e.eeeee2eeeee5eeeeeeee,a,e,r
对此
test1,test2,test3,test4,test10,test11,test12,test17
rh,mbn,ccc,khj,ee3 e,a2,3,u
hyt,bb,mb,khj,R ee3,a,5,r
mbn,htr,ccc,fdf,F1ee ,a,e,r
答案1
如果您的文件确实像您的示例一样简单,您可以执行以下操作之一:
awk
$ awk -F, -vOFS=, 'NR>1{$5=substr($5,1,5)}1' file test1,test2,test3,test4,test10,test11,test12,test17 rh,mbn,ccc,khj,ee3 e,a2,3,u hyt,bb,mb,khj,R ee3,a,5,r mbn,htr,ccc,fdf,F1ee ,a,e,r
解释
将
-F,
输入字段分隔符设置为,
并将-vOFS=,
变量OFS
(输出字段分隔符)设置为,
。NR
是当前行号,因此上面的脚本会将第 5 个字段更改为其自身的 5 个字符的子字符串。唯一的一个1
是 awk 的“打印这一行”的简写。perl
$ perl -F, -lane '$F[4]=~s/(.{5}).*/$1/ if $.>1; print join ",", @F' file test1,test2,test3,test4,test10,test11,test12,test17 rh,mbn,ccc,khj,ee3 e,a2,3,u hyt,bb,mb,khj,R ee3,a,5,r mbn,htr,ccc,fdf,F1ee ,a,e,r
解释
使
-a
perl 的行为类似于 awk 并根据 给定的字符分割其输入行-F
并将它们保存为数组的元素@F
。然后,我们删除第 5 个字段中除前 5 个字符之外的所有字符(它们从 开始计数0
),然后打印@F
用逗号连接的结果数组。sed
$ sed -E '1!s/(([^,]+,){4}[^,]{5,5})[^,]*,/\1,/' file test1,test2,test3,test4,test10,test11,test12,test17 rh,mbn,ccc,khj,ee3 e,a2,3,u hyt,bb,mb,khj,R ee3,a,5,r mbn,htr,ccc,fdf,F1ee ,a,e,r
解释
这是替换运算符,其一般格式为
s/original.replacement/
。意思1!
是“不要在第一行这样做”。正则表达式匹配一组非字符,,
后跟,
4 次 (([^,]+,){4}
),然后是任何 5 个非,
字符 ([^,]{5}
)(这些是第 5 个字段的第 1 个 5),然后是其他任何字符,直到字段末尾 ([^,]+,
)。所有这些都被该行的第一部分替换,有效地截断了该字段。
答案2
使用awk
:
awk -F , 'BEGIN { OFS = FS } NR > 1 { $5 = substr($5,1,5) }; 1' data.csv
该-F
标志设置输入字段分隔符,该BEGIN
块将输出字段分隔符设置为输入字段分隔符(逗号)。
如果当前记录的序号 ( NR
) 大于 1(即我们已经传递了标题行),则该substr()
函数会将第五个字段(列)截断为最多 5 个字符。这可以避免修改输入数据的第一行。
单独的1
将导致将awk
(可能)修改的记录(行)打印到标准输出。