如何用Bash/Awk移除CSV文件行尾的多余分隔符|
问题描述
我有一批CSV文件,格式不规范:文件用“|”作为分隔符,部分文件从第二行开始行尾带有多余的“|”,导致第一行有N列,后续行变成N+1列。想遍历文件移除行尾的多余分隔符,请问用Shell的Awk或类似工具处理单个文件的最优方法是什么?
输入CSV示例:
|some|data|here |some|more|data| |even|more|data|
输出示例:
|some|data|here |some|more|data |even|more|data
最优处理方法
方法一:用Awk处理(更严谨)
Awk可以根据第一行的列数精准判断后续行是否需要处理,避免误删正常行尾内容:
NR==1 { print; cols=NF; next } NF>cols { sub(/\|$/, "", $0) } 1
说明:
- 第一行(
NR==1)直接打印,同时记录当前字段数cols,跳过后续逻辑。 - 后续行如果字段数
NF大于cols(说明行尾多了一个|),就用sub删除行尾的|。 - 最后一行的
1是awk简写,代表打印所有行(包括处理后的和无需处理的行)。
运行方式:
awk 'NR==1 { print; cols=NF; next } NF>cols { sub(/\|$/, "", $0) } 1' input.csv > output.csv
方法二:用Sed处理(更简洁)
如果能确定只有第二行及以后的行才会出现行尾多余的|,用Sed更高效:
'2,$ s/|$//' input.csv
说明:
2,$指定只处理第2行到最后一行。s/|$//表示把行尾的|替换为空(直接删掉)。
运行方式:
sed '2,$ s/|$//' input.csv > output.csv
如果要直接修改原文件(注意先备份),可以加-i参数:
# Linux系统 sed -i '2,$ s/|$//' input.csv # macOS/BSD系统 sed -i '' '2,$ s/|$//' input.csv
批量处理所有CSV文件
如果要处理当前目录下所有.csv文件,用循环即可:
Awk批量处理
for file in *.csv; do awk 'NR==1 { print; cols=NF; next } NF>cols { sub(/\|$/, "", $0) } 1' "$file" > tmp_file && mv tmp_file "$file" done
Sed批量处理
# Linux for file in *.csv; do sed -i '2,$ s/|$//' "$file" done # macOS/BSD for file in *.csv; do sed -i '' '2,$ s/|$//' "$file" done
注意:批量修改前建议先备份文件,避免数据丢失。
内容的提问来源于stack exchange,提问作者abinitio
相关产品推荐
相关产品推荐

