2つの特定の文字列間のすべての文字を表示するには?

2つの特定の文字列間のすべての文字を表示するには?

ファイル内の文字列 "xxx"と "yyy"の間のすべての文字を表示したいです(引用符は区切り文字の一部ではありません)。どうすればいいですか?たとえば、「He​​llo world xxxこれはyyyファイルです」と入力すると、「これはファイルです」と出力する必要があります。

答え1

sed次のようにパターンマッチングフラグを使用できます。

echo "Hello world xxx this is a file yyy" | sed 's/.*xxx \(.*\)yyy/\1/'

これは.*xxx最初から一致するようになりますxxx。以下を使用して表示するのが最善ですgrep

ここに画像の説明を入力してください。

\1まですべてを覚えることができますが、\(.*\)そうでないのは「メモリモード」です。xxxyyyyyy

最後に記憶された文字列を印刷します。

答え2

これにより、目的のタスクが実行されます。

sed -e 's/xxx\(.*\)yyy/\1/'

これは、2つの区切り文字列が同じ行にあると仮定します。

答え3

この質問は、区切り文字が必ず同じ行にある必要がない場合にのみ意味があります。さまざまな方法で実行できますが(使用している場合でもsed)、awkより柔軟です。

    #!/bin/sh
    ああ
    開始{検索= 0;
    /xxx/ {
        if(!検索){
            発見= 1;
            $0 = substr($0, index($0, "xxx") + 3);
        }
    }
    /yyy/ {
        if(検索){
            発見= 2;
            $0 = substr($0, 0, index($0, "yyy") - 1);
        }
    }   
        {もし(検索){
            印刷;
            if(検索==2)
                発見= 0;
        }
    }
    '

行に最大1つの部分文字列がある場合は、次のデータを使用して簡単なテストを実行しました。

    ここはxxx yyです
    最初
    第二年

    xxx.x
    イヤ

    xxx#yyy

そして次の出力(スクリプトは「foo」、データは「foo.in」):

    $猫 foo.in|./foo
     うん
    最初
    第二
    。 X

    #

仕組みは、入力データがあり、$0awkがパターン合計を順番に一致させてデータを印刷する最終段階に行く途中でさまざまな変更を行うことができることxxxです。yyy$0

しかし、この例は以下では機能しません。

xxxxHelloyyyxxxWorldyyy

最初の一致のみを確認するためです。 Perlスクリプトは、awkの例で使用したように、インデックス/サブストリングの代わりにグリディマッチングを使用するため、異なる結果が得られます。もちろん、Perlはスクリプトを使用して同じことを行うこともできます。

Awk(Perlなど)は自由形式なので、コマンドは次のように表現できます。

awk 'BEGIN{found=0;}/xxx/{if(!found){found=1;$0=substr($0,index($0, "xxx")+3);}}/yyy/{if(found){found=2;$0=substr($0,0,index($0,"yyy")-1);}}{ if(found){print;if(found==2)found=0;}}'

しかし、これは例を除いてほとんど行われません。同様に、sedスクリプト(行ベース)は、いくつかの制限を除いて1行にまとめることができます。同様に、複雑なスクリプトはsedこのように処理されることはほとんどありません。代わりに、実際のプログラムとして扱われます(参照:はい)。

追加資料:

答え4

xxx同じ行にあるときとない場合でもyyy動作するソリューション: cat /tmp/xxx-to-yyy| perl -ne '(/xxx/../yyy/) && print' | perl -pe 's/.*(xxx.*)/$1/' | perl -pe 's/(.*yyy).*/$1/'

あまりきれいではありません...

コマンドラインからスクリプトを提供することに-e切り替えました。入力行を繰り返し作成し、perlスクリプトの後に印刷しますが、そうではありません。したがって、デフォルトでは、これは3つのPerlループを介してファイルを送信します。-n-p-p-n

..左の条件が true を返す前に false を返し、右の条件が true を返した後に false を返す範囲演算子です。したがって、最初のループはファイルを2つの文字列(両方を含む)の間の行に切り捨てます。最後の 2 つの perl コマンドは、xxx前と右の条件のテキストを削除します。後yyy

関連情報