使用shell脚本删除换行符

时间:2012-06-08 08:24:20

标签: perl shell sed awk

我有一个文本文件,如下所示。它有一些额外的换行符我想删除。

LINE1: @Line1Col1 @Line1Col2

LINE2: @Line1Col3 @Line1Col4 @ Line1Col5@

LINE3: @Line2Col1 @Line2Col2 @Line2Col3

LINE4: @Line2Col4@

LINE5: Line2Col5 @

我想删除换行符,使其看起来像这样:

@Line1Col1 @Line1Col2 @Line1Col3 @Line1Col4 @Line1Col5@

@Line2Col1 @Line2Col2 @Line2Col3 @Line2Col4@ Line2Col5@

如果一行以@分隔符开头并以@分隔符结束,则该行被定义为完成。 请注意,分隔符@已存在于文件中。 例如,附加LINE1和LINE2可使线条完整。 类似地,附加LINE3,LINE4和LINE5会产生另一条完整的行(在每行上,数据LineXcolX用于说明目的)。 因此,我需要删除LINE1中的换行符并在LINE2中保留换行符。 同样,我需要删除LINE3和LINE4中的换行符并在LINE5中保留换行符。 中间可以有多个空格;因此,空间不能用于解决方案。

重新编辑[添加了实际文件的一部分]

我能想到的一个逻辑就是只保留新行,因为上一行的结尾是" @"当前行以" @"开头。 但是,我不确定如何在shell中实现它,或者是否有更好的逻辑。

@ 258908159 @ 258908159 @ Subwork = E,Mment = SS09 @ 4 @ Jun 5 2012 23:24:41 @Jun 5 2012 23:24:00 @ 2 @ * " DUMMYI" U 120605 DUMMY DATA @Jun 5 2012 23:26:00 @ 403 @ 21 @ PRCAIE @ 10780093 @ -2 @ @ -1 @ -2 @ 1 @ 35 @ 1 @ @ -1 @ NULL @ -1 @ 154 @ 1 @ 40958044 @ 1 @ 1 @ 3 @ 0 @ -2 @ 1 @ @ 258908158 @ 258908158 @ Subwork = E,Mment = SS09 @ 4 @ Jun 5 2012 23:24:41 @Jun 5 2012 23:24:00 @ 2 @ 3TEST3
结束@Jun 5 2012 23:26:00 @ 402 @ 21 @ @ 10780093 @ -2 @ @ -1 @ -2 @ 1 @ 35 @ 1 @ @ -1 @ NULL @ -1 @ 154 @ 1 @ 40958044 @ 1 @ 1 @ 3 @ 0 @ -2 @ 0 @

#####需要新行此处必须删除所有其他新行

@ 258908158 @ 258908158 @ Subwork = E,Mment = SS09 @ 4 @ Jun 5 2012 23:24:41 @Jun 5 2012 23:24:00 @ 2 @ * " DUMMYI" U 120605 DUMMY @Jun 5 2012 23:26:00 @ 402 @ 21 @ PRCAIE @ 10780093 @ -2 @ @ -1 @ -2 @ 1 @ 35 @ 1 @ @ -1 @ NULL @ -1 @ 154 @ 1 @ 40958044 @ 1 @ 1 @ 3 @ 0 @ -2 @ 1 @ @ 258908157 @ 258908157 @ Subwork = E,Mment = SS09 @ 4 @ Jun 5 2012 23:24:41 @Jun 5 2012 23:24:00 @ 2 @ 3TEST3
结束@Jun 5 2012 23:26:00 @ 401 @ 21 @ @ 10780093 @ -2 @ @ -1 @ -2 @ 1 @ 35 @ 1 @ @ @ -1 @ NULL @ -1 @ 154 @ 1 @ 40958044 @ 1 @ 1 @ 3 @ 0 @ -2 @ 0 @

感谢。

3 个答案:

答案 0 :(得分:1)

我的理解是,随着我们的进展,我们会连接并存储行。如果当前行以“@”开头并且存储的连续批次以“@”结尾,则我们处于行边界。然后我们打印存储的批次并重新开始。

awk '/^@/ && l~/@$/ { print l; l=$0; next } { l=l $0} END { print l }'

答案 1 :(得分:0)

这可能对您有用:

sed ':a;$bb;N;/@ *\n *@/!{y/\n/ /;ba};:b;P;D' file

说明:

删除除@所包围的所有换行符之外的所有换行符:

  • 为循环制作标签::a
  • 如果最后一行中断到第二个标签b$bb
  • 在模式空间中附加下一行。 N
  • 查找@符号所包围的换行符。 /@ *\n *@/
  • 如果没有这样的模式,请将换行符转换为空格并循环到标签a!{y/\n/ /;ba}
  • 找到模式(所有换行都已准备就绪)或文件结束条件。打印到换行符。 :b;P
  • 删除上面的打印行并开始新的循环(不要读下一行)。 D

更神秘的解决方案:

 sed '$!{N;/@ *\n *@/!{s/\(.*\)\n/\n\1/;D}};P;D' file

答案 2 :(得分:0)

这个简单的Perl程序应该做你想要的。

它通过连接输入文件中的行并在累积的字符串包含一对@符号时拆分,可能用空格分隔。

请注意,它希望输入文件作为命令行上的参数,并将修改后的数据发送到STDOUT。

use strict;
use warnings;

my $line;

while (<>) {
  chomp;
  $line .= $_;
  while ($line =~ s/^(.+?\@)\s*(?=\@)//) {
    print $1, "\n";
  }
}

print $line, "\n";

输出(使用您的示例输入数据)

@Line1Col1 @Line1Col2@Line1Col3 @Line1Col4 @ Line1Col5@
@Line2Col1 @Line2Col2 @Line2Col3@Line2Col4@Line2Col5 @

<强>更新

它从您的实际文件数据中查看,好像在记录中间可以有两个@,因此上述方法将无效。

但看起来你正在处理@ - 分开的数据,分析它告诉我每条记录有25个字段,意味着26个@个字符。

此备用程序累积数据,直到它包含26个或更多@个字符,然后输出它。它似乎适用于您发布的实际数据。

use strict;
use warnings;

my $line;

while (<>) {
  chomp;
  $line .= $_;
  if ($line =~ tr/\@// >= 26) {
    print ">>", $line, "\n";
    undef $line;
  }
}

print $line, "\n" if $line;