このスレッドは、このスレッドへのリンクにある算術コマンドによって動機付けられます。ここ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
前のスペースとパターンスペースはx
eによって変更されます。もしあれば!
いいえ\n
パターン空間でewlineをリードしてからsed
q
入力を満たします。突然追加入力の読み込みが中断されました。(またはスクリプトでより多くのコマンドを実行します。たとえばd
)別言します。しかし、リード\n
線が除去され、h
古いパターン空間がx
再び変更され、パターン空間がd
除去される。
その結果、最初に出会った行は保持され、それが示す最初の発生タグはこれをq
uitting入力から保存しますが、第二発生した場合は処理を終了します。
しかし、私が誤解したのではないでしょうか?ファイル内の最初の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のため、現在は信頼できません。上記は文字クラスを使用しているため、upper
Unicodelower
に安全です。[[: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
単語を除くすべての項目を削除します。