删除模式之间的换行符

删除模式之间的换行符
foo
I love
Stack Exchange
bar
Some junk
lines
foo
Welcome to the
world of
Bash
bar
foo
Elon Musk
rocks

是的,文件末尾没有bar补码foo

所需的输出是

I love Stack Exchange
Welcome to the world of Bash
Elon Musk rocks

因此,删除所有换行符,在^fooand之间^bar或在^fooand之间,end of file其中没有bar

答案1

awk

awk '
  $0 == "foo" {if (sep) print ""; sep = ""; inside = 1; next}
  $0 == "bar" {inside = 0; next}
  inside {printf "%s", sep $0; sep = " "}
  END {if (sep) print ""}'

要匹配foo第一个单词为 的行,请替换$0 == "foo"$1 == "foo";要匹配以 开头的行foo,请替换为/^foo/( 的缩写$0 ~ /^foo/)。

答案2

Perl 来救援!

perl -ne '
    if ($e = /^foo$/ .. /^bar$/) {
        if ($e =~ /E/) { print "\n" }
        else {
            chomp;
            print " " if $e > 2;
            print     if $e > 1;
        }
}' -- input.txt
  • -n逐行读取输入
  • ..是范围运算符,它返回块中每一行的相对行号。最后一行已E0附加到其上。

答案3

你也可以这样做:

a) 这是POSIX-sed兼容的代码,其中我们将中范围线(!/foo/ 和 !/bar/)存储在保留区域中。

sed -e '
    /foo/,/bar/!d
    /foo/d
    /bar/!{H;$!d;}
    s/.*//;x;s/^\n//;y/\n/ /
' input-file.txt

b) 并Perl如图所示

perl -lne '
   next unless /foo/ ... /bar/;
   push(@A, $_),next if !/foo/ && !/bar/ && !eof;
   push(@A, $_)      if !/foo/ && !/bar/ &&  eof;
   print join " ", splice @A if /bar/ || !/foo/ && eof;
' input-file.txt

解释:

  • 跳过不感兴趣的行或超出范围的行。范围定义为以包含 的行开始/foo/并以 结尾/bar/,两者出现在不同的行上。
  • 一旦我们进入范围,然后根据我们所在的线执行单独的操作。
  • 对于不是 /foo/ 、 /bar/ 和 eof 的行:将该行存储在数组中@A。存储完成后,返回读取下一条记录(不是eof)。
  • 仅对于范围的末尾,即/bar/eof,我们采取打印内容@A并清空它的操作,为下一个收集周期做准备。

相关内容