需求:用bash/sed/awk/perl编写脚本,删除下一行短于指定长度的行的换行符
刚好做过类似的需求,给你整理几个用不同工具实现的方案,每个都带示例和注释,你可以根据自己的习惯选:
需求明确
当文本中某一行的下一行长度小于指定阈值时,删除当前行的换行符,将两行合并成一行。下面以阈值=5为例(即下一行字符数<5时合并),给出具体实现。
示例输入与预期输出
示例输入(input.txt)
这是第一行,长度明显超过阈值 短行 这是第二行,长度也符合要求 更短 最后一行,正常输出
预期输出
这是第一行,长度明显超过阈值短行 这是第二行,长度也符合要求更短 最后一行,正常输出
方案1:用awk实现(最直观易读,适合新手)
awk的逻辑非常清晰,通过保存上一行来和当前行做判断:
#!/usr/bin/awk -f # 在这里设置长度阈值,比如我们设为5 BEGIN { threshold = 5 } # 从第二行开始处理(第一行没有上一行) NR > 1 { # 如果当前行长度小于阈值,就把上一行的换行去掉,直接拼接 if (length($0) < threshold) { printf "%s", prev_line } else { # 否则正常输出上一行 print prev_line } } # 把当前行存起来,作为下一次循环的"上一行" { prev_line = $0 } # 最后处理最后一行,不管怎样都要输出 END { print prev_line }
使用方法:
- 把上面的代码保存为
merge_short_lines.awk - 运行命令:
awk -f merge_short_lines.awk input.txt - 如果要临时调整阈值,直接在命令行传参:
awk -v threshold=3 -f merge_short_lines.awk input.txt
方案2:用sed实现(一行命令,适合快速处理)
sed用保持空间来实现行的暂存,适合写单行命令快速处理:
# 阈值=5,对应匹配换行后0-4个字符的行(.{0,4}) sed -E ':loop; $!{N; /\n.{0,4}$/s/\n//; t loop; P; D}' input.txt
命令解释:
:loop:定义循环标签,处理连续短行的情况(比如下一行合并后,再下一行还是短行,会继续合并)$!{...}:除了最后一行都执行里面的逻辑N:把下一行读入到模式空间,和当前行用换行分隔/\n.{0,4}$/:匹配模式空间中,换行符后面跟着小于5个字符的行s/\n//:匹配成功就删除换行符,合并两行t loop:如果替换成功,回到loop标签继续处理(处理连续短行)P:打印模式空间中换行符之前的部分D:删除模式空间中换行符之前的部分,重新循环
如果只需要合并当前行和下一行(不管下下一行),可以简化成:
sed -E '$!N; /\n.{0,4}$/s/\n//; P; D' input.txt
方案3:用Perl实现(灵活强大,适合复杂扩展)
Perl的语法更灵活,适合后续需要加更多逻辑的场景:
#!/usr/bin/perl use strict; use warnings; # 设置长度阈值 my $threshold = 5; my $prev_line; # 读取输入文件(支持命令行传多个文件,或者从管道读) while (my $line = <>) { chomp $line; # 去掉每行末尾的换行符 if (defined $prev_line) { # 判断当前行长度是否小于阈值 if (length($line) < $threshold) { print $prev_line; # 不输出换行,直接拼接 } else { print "$prev_line\n"; # 正常输出上一行 } } # 把当前行存为下一次循环的"上一行" $prev_line = $line; } # 最后输出最后一行 print "$prev_line\n" if defined $prev_line;
使用方法:
- 保存为
merge_short_lines.pl - 运行命令:
perl merge_short_lines.pl input.txt - 调整阈值直接修改
$threshold变量即可
内容的提问来源于stack exchange,提问作者Powers
相关产品推荐
相关产品推荐

