【问题标题】:Text manipulation and removal文本操作和删除
【发布时间】:2009-11-20 01:11:48
【问题描述】:

我有一个由我的工具生成的文本文件,其结构如下所示。

1 line text
(space)
multiple
lines
text
(space)
multiple
lines
text
nr 2
---------------------------------------------------------- (58 '-' characters)
different 1 line text
(space)
different
multiple
lines
text
(space)
different
multiple
lines
text
nr 2
----------------------------------------------------------
different 1 line text
(space)
different
multiple
lines
text
(space)
different
multiple
lines
text
nr 2
----------------------------------------------------------
(space)

每个文件以 1 行文本开头,以“-”符号分隔符和空格结尾。每个文件中有不同数量的节,并且“中间”的每个节都以“-”符号开始和结束。以下是我想要实现的目标。

multiple
lines
text
(space)
different
multiple
lines
text
(space)
different
multiple
lines
text

我想删除所有一个衬里、所有 58 个“-”字符分隔符和所有“第二个”多个衬里,并且每个部分中只有“第一个”多个衬里一个在另一个下一个用空格分隔。有人可以推荐如何在linux上做到这一点吗?任何建议都会有所帮助。

【问题讨论】:

  • 谁投票决定关闭属于 SU? sed 是一种编程语言,无论多么原始,这是一个公认的先例。无论如何,最好用 awk/perl 解决方案来回答这个问题。
  • “(空格)”是指空格字符、换行符、空格(空格、换行符、制表符)还是其中一个或多个的倍数?
  • 另外,在您想要的结果示例中,是否应该包含“nr 2”的行以与“每个部分只有'第二个'多个衬里”保持一致?跨度>
  • 对不起,这是一个错字,我的意思是第一个多个衬里,而不是第二个......就像我写的输出示例一样

标签: linux bash sed


【解决方案1】:
perl -00 -ne 'print if $.%2==0' 

-00 标志将记录分隔符设置为空行。

【讨论】:

    【解决方案2】:

    编辑:打印第一个多行组:

    awk 'BEGIN {toggle=1} /^\(space)$/ {if (!toggle) print ""; toggle=!toggle; next} {if (! toggle) print}' file.txt
    

    原文:打印第二个多行组:

    awk '/^\(space)$/ { accum=""; next} /^-+$/ {print accum; accum=""; next} {accum=accum"\n"$0}' file.txt
    

    【讨论】:

    • 我使用"(space)" 作为文字字符串,但您可以将其更改为/^$/ 以检查是否有空行。
    【解决方案3】:

    下面的perl 脚本会做你想做的事(我发现sed 不太适合跨多行的任务)。

    #!/usr/bin/perl
    
    $first = 1;
    $skip = 2;
    while (<>) {
        chomp;
        $ln = $_;
        if ($ln =~ /^-{58}$/) {
            $skip = 2;
            next;
        }
        if ($skip > 0) {
            $skip--;
            if ($skip == 0) {
                if ($first) {
                    $first = 0;
                } else {
                    print "\n";
                }
            }
            next;
        }
        if ($skip == 0) {
            print $ln . "\n";
            if ($ln =~ /^$/) {
                $skip = -1;
            }
        }
    }
    

    这是基于您的(space) 行只是空行的假设。如果不是,您需要调整底部附近的/^$/ 模式以匹配它的实际情况。

    它基本上是一个由$skip 变量控制的简化状态机。如果这是肯定的,那么您将跳过那么多行(从 2 开始,每 --- 行设置为 2)。

    $skip 达到零时,它会一直停留在那里,直到你得到一个空行(你正在回显这些行)。当你得到一个空行时,你将它设置为 -1 并停止回显这些行。

    $first 变量有点小技巧,可以确保输出中没有尾随空行。

    这是我从您的输入文件中得到的输出:

    multiple
    lines
    text
    (space)
    different
    multiple
    lines
    text
    (space)
    different
    multiple
    lines
    text
    

    我相信这就是你所追求的。

    【讨论】:

      【解决方案4】:

      我会选择awk 而不是sed。建立一个列表,直到您点击/-+$/,然后输出您存储的多行部分,直到每条虚线。

      编辑:在那之前我会使用 perl,但 awk 也很有趣。

      【讨论】:

        【解决方案5】:

        呆呆

        awk  '{ print $2 }' RS="-\n" FS="\n\n" file
        

        输出

        $ ./shell.sh
        multiple
        lines
        text
        different
        multiple
        lines
        text
        different
        multiple
        lines 
        text
        

        Perl 中的等价物。

        $\ = "\n";
        $/ = "-\n";
        while (<>) {
            chomp;
            ($f1,$f2) = split "\n\n", $_ ;
            print $f2;
        }
        

        【讨论】:

        • 你可能需要修改它,因为它不输出空行。
        • 我会把它留给 OP 作为练习。
        猜你喜欢
        • 2023-03-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多