Linux Shell脚本中如何仅替换CSV第5列的点号
问题:仅替换CSV指定列中的点号
我有一个output.csv文件,内容如下:
No | Timestamp | Table | agg | result | percentage | status | year | month | day 2022-09-30 00:00:00|2022-09-30 00:00:00|Source|count|287.472.321|-4.83%|Normal|2022|202209|20220930 2022-09-30 00:00:00|2022-09-30 00:00:00|Source|count|498.512.903|-4.05%|Normal|2022|202209|20220930 2022-09-30 00:00:00|2022-09-30 00:00:00|Source|count|19.089.222|-19.4%|Normal|2022|202209|20220930 2022-09-30 00:00:00|2022-09-30 00:00:00|Source|count|29.014.921|-2.47%|Normal|2022|202209|20220930 2022-09-30 00:00:00|2022-09-30 00:00:00|Source|count|148.770.415|-0.14%|Normal|2022|202209|20220930
需要将第5列中的点号(.)替换为空,同时不影响第6列的点号,处理后效果如下:
2022-09-30 00:00:00|2022-09-30 00:00:00|Source|count|287472321|-4.83%|Normal|2022|202209|20220930 2022-09-30 00:00:00|2022-09-30 00:00:00|Source|count|498512903|-4.05%|Normal|2022|202209|20220930 2022-09-30 00:00:00|2022-09-30 00:00:00|Source|count|19089222|-19.4%|Normal|2022|202209|20220930 2022-09-30 00:00:00|2022-09-30 00:00:00|Source|count|29014921|-2.47%|Normal|2022|202209|20220930 2022-09-30 00:00:00|2022-09-30 00:00:00|Source|count|148770415|-0.14%|Normal|2022|202209|20220930
曾尝试使用命令:
cat output.csv | grep -v -i "No " | sed 's/\.//g' > output3.csv
但该命令会替换所有列中的点号,如何在Linux Shell脚本中实现仅替换第5列的点号,同时保留CSV格式?
解决方案
方法1:使用awk(推荐,直观易维护)
awk原生支持列操作,直接定位第5列进行替换,同时保留表头:
awk -F'|' 'NR==1{print; next} {gsub(/\./, "", $5); print}' OFS='|' output.csv > output_processed.csv
-F'|':设置输入分隔符为|NR==1{print; next}:第一行是表头,直接输出并跳过后续处理gsub(/\./, "", $5):在第5列中全局替换所有点号为空OFS='|':设置输出分隔符为|,保证CSV格式不变
方法2:使用sed(适合轻量处理)
通过正则分组捕获,仅对第5列的内容进行替换:
sed -E '/^No /!s/^(([^|]*\|){4})([^|]*)(\|.*)$/\1'"$(echo '\3' | sed 's/\.//g')"'\4/' output.csv > output_processed.csv
或者GNU sed支持的更简洁写法:
sed -E '/^No /!{s/^(([^|]*\|){4})([^|]*)/\1\3/; s/\.//g3}' output.csv > output_processed.csv
/^No /!:跳过表头行- 正则分组将每行拆分为「前4列」「第5列」「剩余列」三部分,仅对第5列的内容替换点号后重新拼接
方法3:使用perl
perl的数组操作也能轻松实现列定位替换:
perl -F'\|' -lane 'if($.==1){print}else{$F[4] =~ s/\.//g; print join("|", @F)}' output.csv > output_processed.csv
-F'\|':指定分隔符为|-lane:自动读取每行,将内容拆分到数组@F(索引从0开始,第5列对应$F[4])$.==1:表头行直接输出$F[4] =~ s/\.//g:替换第5列的所有点号join("|", @F):用|拼接数组,输出处理后的行
内容的提问来源于stack exchange,提问作者cankcimen
相关产品推荐
相关产品推荐

