如何用awk移除文件中的特定意外换行符?
解决大文件中意外换行符的移除问题
问题场景
有一个1000万行的大文件,存在需要移除的意外换行符。示例输入:
uno field, dos field, tres field, cuatro field, cinco field, seis field, siete field one field, two field, three field, four field, five field ichi field, ni field, san field
期望输出:
uno field, dos field, tres field, cuatro field, cinco field, seis field, siete field one field, two field, three field, four field, five field ichi field, ni field, san field
尝试用sed -z 's/four\n/four /g' input.txt仅在小文件子集有效,大文件失效;测试awk命令awk '/four\n/ {print}' input.text无输出,需要可行方案。
原因分析
- sed -z的问题:
-z选项会将整个文件以NUL字符为分隔符读入内存,1000万行的大文件内存占用极高,超出处理能力,因此仅小文件有效。 - awk命令无效的原因:awk默认按行读取内容,每行内不包含换行符,
/four\n/这个正则无法匹配到任何行,自然没有输出。
可行解决方案
方案1:使用awk逐行处理(低内存占用,适合大文件)
利用awk的行缓存功能,判断上一行是否为需要拼接的不完整行,将下一行拼接到上一行末尾:
NR>1 { if (prev ~ /four$/) { printf "%s ", prev prev = $0 } else { print prev prev = $0 } } END { print prev }
使用方式:
# 写成脚本文件执行 awk -f script.awk input.txt > output.txt # 或者直接一行命令执行 awk 'NR>1{if(prev~/four$/){printf "%s ",prev;prev=$0}else{print prev;prev=$0}}END{print prev}' input.txt > output.txt
方案2:使用sed多行处理(更简洁)
用sed的多行匹配功能,仅处理需要拼接的行,无需加载整个文件:
'/four$/{N;s/\n/ /}' input.txt > output.txt
命令解释:
/four$/:匹配以four结尾的行{N;s/\n/ /}:将下一行读入当前模式空间,然后把两行之间的换行符替换为空格
补充说明
如果意外换行的触发条件不止four结尾(比如所有不完整行都不以逗号结尾),可以修改正则实现通用匹配:
awk版本修改为:
NR>1 { if (prev !~ /,$/) { printf "%s ", prev prev = $0 } else { print prev prev = $0 } } END { print prev }
sed版本修改为:
'/[^,]$/{N;s/\n/ /}' input.txt > output.txt
内容的提问来源于stack exchange,提问作者Reuben Romero
相关产品推荐
相关产品推荐

