Sedで名前の前に単語を検索する

Sedで名前の前に単語を検索する

このスレッドは、このスレッドへのリンクにある算術コマンドによって動機付けられます。ここSedでリバース演算を実行したいです。

データ

Mikael symptom
David symptom
hello symptom

このコマンドは最初の2つの項目を返す必要があります。 PerlのLookbehindは1つの方法ですが、Sedがそれをできるかどうかを確認したかったのです。

擬似コードのメソッド

  • 一致する名前: g/[A-Z]\w\w/;is.words[2]('symptom')

後ろを見て

  • Match symptom;次の名前を探します。名前があれば返します。

Sedでこの擬似コードを書くことはできますか?

答え1

sed '/^[[:upper:]][[:lower:]]\{1,\} symptom$/!d
    H;x;/^\n/!q;s///;x;d'

これは大文字で始まり、その後に1つ以上の小文字が続く行を見つけ、1つだけを検索します。<スペース>そして文字列兆候。現在の行が一致しない場合はd削除され、次の入力行からスクリプトが一番上から再起動されます。

その場合する一致は、H挿入された行区切り文字の後の前のスペースにコピーされます\n。このようなことが初めて発生すると、h既存の空間は空になるので、主人公は\nユーラインになります。一致する行がH削除された後、h前のスペースとパターンスペースはxeによって変更されます。もしあれば!いいえ\nパターン空間でewlineをリードしてからsed q入力を満たします。突然追加入力の読み込みが中断されました。(またはスクリプトでより多くのコマンドを実行します。たとえばd別言します。しかし、リード\n線が除去され、h古いパターン空間がx再び変更され、パターン空間がd除去される。

その結果、最初に出会った行は保持され、それが示す最初の発生タグはこれをquitting入力から保存しますが、第二発生した場合は処理を終了します。

しかし、私が誤解したのではないでしょうか?ファイル内の最初の2つの一致だけが欲しいということを意味します。

欲しいなら名前もし症状$これはとても簡単です。

sed -n '/^[[:upper:]][[:lower:]]\{1,\} [^ ]*$/s/ symptom$//p'

ここでは、私たちが実際に探していることを確認します。可能交換を試みる前に行を一致させてくださいs///-s///交換は次のようになります。機能親アドレス。 trueの場合は、不要な尾を切り取り、p成功した場合にのみ印刷しようとします。両方頭と尾の状態を確認する前に。

答え2

私が理解しているように、大文字の単語とその後に大文字の単語を含む行を印刷したいと思いますsymptom。この場合:

$ sed -rn '/\b[[:upper:]][[:lower:]]*[[:space:]]+symptom/p' data
Mikael symptom
David symptom

便宜上\b、whichを使用して単語の境界を示します。これは少なくともGNU sedでサポートされています。あなたのsedがサポートしていない場合は教えてください。

仕組み:

基本的な形式は次のとおりです。

sed -n '/pattern/p' file

これは一致する行だけを印刷しますpattern。私たちの場合、パターンには以下が含まれます。

  • \b

    これは単語の境界でのみ一致します。

  • [[:upper:]][[:lower:]]*

    これは、大文字の後にゼロ個以上の小文字が続くものと一致します。

    古代にはこれがこう書かれている可能性があることに注意してください[A-Z][a-z]+。 Unicodeのため、現在は信頼できません。上記は文字クラスを使用しているため、upperUnicodelowerに安全です。

  • [[:space:]]+symptom

    これは、1つ以上のスペースの後に単語が続くものと一致しますsymptom

選ぶ

前の名前だけを印刷したいとしましょうsymptom

$ sed -rn 's/\b([[:upper:]][[:lower:]]*)[[:space:]]+symptom.*/\1/p' data
Mikael
David

答え3

sed -n '/^[[:upper:]]\w* symptom/s/ .*//p'

大文字で始まる行を印刷し、最初のsymptom単語を除くすべての項目を削除します。

関連情報