【问题标题】:Remove newline char using shell script使用 shell 脚本删除换行符
【发布时间】:2012-06-08 08:24:20
【问题描述】:

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

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 虚拟数据 @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@2012 年 6 月 5 日 23:24:41 @2012 年 6 月 5 日 23:24:00 @ 2@ 3TEST3
结束@2012 年 6 月 5 日 23:26:00 @ 402@ 21@ @ 10780093@ -2@ @ -1@ -2@ 1@ 35@ 1@ @ -1@ NULL@ -1@ 154@ 1@ 40958044@ 1@ 1@ 3@ 0@ -2@ 0@

#####New Line is required 这里必须删除所有其他新行

@ 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@2012 年 6 月 5 日 23:24:41 @2012 年 6 月 5 日 23:24:00 @ 2@ 3TEST3
结束@2012 年 6 月 5 日 23:26:00 @ 401@ 21@ @ 10780093@ -2@ @ -1@ -2@ 1@ 35@ 1@ @ -1@ NULL@ -1@ 154@ 1@ 40958044@ 1@ 1@ 3@ 0@ -2@ 0@

谢谢。

【问题讨论】:

  • 基于您粘贴的示例文件内容的原始位:在我看来,不可能知道在哪里放置正确的换行符,因为没有“模式”可以帮助您识别.我认为可以解决的唯一方法是:您可以计算“@”字符的数量,并在第 N 个“@”之后换行。
  • 请编辑您的示例输入/输出以展示您的要求。
  • 无法从新输入(来自 RE-EDITED 部分)获取Line1Line2(如Line2Col1)。请明确您希望新输入的输出。
  • @ 258908158@ 258908158 ,整个模式在@ 258908159@ 258908159 中出现两次,第二次包含@ 258908157@ 258908157。这部分需要澄清。

标签: perl shell sed awk


【解决方案1】:

我的理解是,我们会在进行过程中连接和存储行。如果当前行以“@”开头并且存储的串联批次以“@”结尾,那么我们处于行边界。然后我们打印存储的批次并重新开始。

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

【讨论】:

  • +1,小简化:/^@/ && l~/@$/ {print l; l=""} {l=l $0} END {print l}
【解决方案2】:

这个简单的 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 @

更新

从您的实际文件数据来看,好像一条记录中间可以有两个@s,所以上面的方法不起作用。

但看起来您正在处理@-分隔的数据,分析它告诉我每条记录有 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;

【讨论】:

  • 不会有带有@@ 的条目,因此您的解决方案都有效。我更喜欢 Balint 提供的 awk 解决方案,因为它可以轻松集成到我的脚本中。
【解决方案3】:

这可能对你有用:

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

解释:

删除除@'s 包围的所有换行符:

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

一个更神秘的解决方案:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-23
    • 2012-11-14
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多