パターン間の改行の除去

パターン間の改行の除去
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

^fooだから、私との間^barにあるすべての改行文字を削除してください。^fooend of filebar

答え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入力を1行ずつ読みます。
  • ..ブロック内の各行の相対行番号を返す範囲演算子。最後の行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

関連情報