長すぎます。

長すぎます。

デフォルトでは、2つの文字列間の内容を取得しようとしていますが、次のように同じ文字をN回繰り返します。

===
This is a test
===

====
Another test
====

==
Last test
==

もちろん、上記は単なる例です。私の試みと結果は次のとおりです。

sed -u '/==/!d;s//&\n/;s/.*\n//;:a;/==/bb;$!{n;ba};:b;s//\n&/;P;D' testfile

与える

=
This is a test

=




Another test






Last test


上記のいずれかを使用する場合testfile


Last test


これにより、必要な結果が得られます(ただし、改行があまりにも多くなりますが、この例では問題ありません)。

上記の方法は、これらの繰り返し文字のインスタンスが1つしかない場合、または内容を含む一意の文字列ペアである場合にのみ機能します。

繰り返される文字数が同じ2つの文字列間の内容を取得するには?私はこれを使用するか、grepそれを達成することをsed好みます。awk

答え1

私たちは使用アッ次のトリガロジックを使用して開いた状態から閉じた状態に切り替えるユーティリティです。

$ awk -v str="==" '
      $0""==str{f=!f;next};f
' testfile
Last test

Posixlyを使うsedトリガロジックの構成を実装できます。

sed -ne '
  /^==$/{
    x;        # access state info from hold
    s/^$/0/;  # initialize state
    y/01/10/; # toggle state
    x;        # save state in hold
    d;        # next
  }
  G;/\n1/P
' testfile

ストリームエディタのGNUバージョンを使用するsed拡張モードで-E

$ sed -Ee '
    $!N; /^(\S)\1+\n/!D
    :loop
        $d;N
        s/^(.*)\n(.*)\n\1$/\2/;t
    bloop
' testfile
This is a test
Another test
Last test

メモ:-

  • コマンドを介してN2行のパターンスペースを維持します。
  • ゴールデンラインに達するまでラインを拒否し続けます(=>パターンスペースの最初の部分には空白以外の文字の単一タイプのみが含まれています)。
  • そのような線を見つけたら、道路上の線と正確に一致する複製が複数表示されるまで繰り返します。私たちは最初のグループを見つけました。
  • eofに達するまでこのプロセスを繰り返します。

...トリガー演算子の使用真珠次のようにこれを行うことができます。

perl -lne 'print if 
 /^(\S)\1+$(?{$a=$_})/ ... $_ eq $a and $_ ne $a;
' testfile

固定された所定の文字列を検索する方がはるかに簡単です。それ以降は正規表現を書く必要はなく、文字列同等性テストで十分です。

$ perl -nlse 'print if
    $_ eq $a ... $_ eq $a and $_ ne $a;
' -- -a=== testfile

$ sed -Ee '
    /^==$/!d
    $!N
    :a
        $d;N
        s/^(.*)\n(.*)\n\1$/\2/;t
    ba
' testfile

答え2

長すぎます。

$ sed '/^==*$/,//{//!p};d' testfile
This is a test
Another test
Last test

一見すると、単純な範囲はすべてのペアを印刷します(ループは必要ありません)。

$ sed -n '/^=/,//p' testfile
===
This is a test
===
====
Another test
====
==
Last test
==

=()で始まる行と次の繰り返し正規表現()の間の//すべての行を印刷します。

ラインで改善できます。ただ含まれています=/^==*$/

すべてのマーカーを削除します。

$ sed -n '/^==*$/,//H;${x;s/\n==*//g;s/^\n//;p}' testfile
This is a test
Another test
Last test

またはより短い形式で:

$ sed -n '/^==*$/,//{//d;p}' testfile
This is a test
Another test
Last test

正確な数量を一致させるには、=正規表現を次のように変更します。

$ sed -n '/^==$/,//{//d;p}' testfile
Last test

そして、その-nオプションを避けるには:

$ sed '/^==$/,//{//!p};d' testfile
Last test

awkでは、次のようにできます。

$ awk 'p==0 && /^==*$/ {p=1;next}
       p==1 && /^==*$/ {p=0}
       p          
      ' testfile

This is a test
Another test
Last test

またはあまり明示的ではありません:

awk ' /^==*$/ { p = !p ; next}
      p
    ' testfile

答え3

私は以下を使用しますperl

$ perl -0777 -ne 'print $3 while /^((\S)\2+\n)(.*?)^\1/smg' < your-file
This is a test
Another test
Last test

またはpcregrep:

$ pcregrep -Mo3 '(?s)^((\S)\2+\n)(.*?)\n?^\1' < your-file
This is a test
Another test
Last test

固定区切り記号間のコンテンツを返す場合:

$ pcregrep -Mo1 '(?s)^==\n(.*?)\n?^==$' < your-file
Last test

答え4

注文する:

awk '{a[++i]=$0}/==/{for(x=NR-1;x<NR;x++)print a[x]}' filename|sed '/^$/d'

出力

This is a test
Another test
Last test

関連情報