2016-04-29 30 views
0

は、私はこのようなリストを持っている:awkまたはgrepを使って最初のキーワードが一致する前に2番目のキーワードの最初の一致を検索する方法は?

TAGDESCRIPTIONS example 
TAGS   tmp 
TAGS   line 
TAGDESCRIPTIONS bar 
TAGS   com      
TAGS   foo  

それはfooの一致を取得した後TAGDESCRIPTIONSラインと一致しているためにはawkやgrepの右のコマンドは何ですか?したがって、fooを検索すると、barが印刷されます。

答えて

1

Grepのは、このためには適していませんが、あなたは別のライン間の関係について尋ねます。 Grepはに何度か強制することができます複数の行にまたがるもの(ab)は、ヌルバイトで区切られた行を必要とする-zフラグを使用しますが、通常はそれほど美味しくありません。

Awkのは、簡単な解決策を可能にする:これは、RSTAGDESCRIPTIONSにレコードセパレータを設定

$ awk 'BEGIN{RS="TAGDESCRIPTIONS"}/foo/{print $1}' infile 
bar 

ので、入力は、3つのレコード(改行\n意味する)として解釈される:

<empty record> 
example\nTAGS   tmp\nTAGS   line\n 
bar\nTAGS   com\nTAGS   foo\n 

ファイルがレコードセパレータで始まるため、最初のファイルは空です。

各レコードについて、最初の改行まではタグの説明です。私たちは

/foo/{print $1} 

と言うことはこれです:レコードは、レコード(説明)の最初のフィールドを印刷、fooに一致する場合。

これはまったく爆弾ではありません。記述が複数の単語で構成されている場合は、最初のものだけが出力されます。タグの代わりに説明が一致すると、それは偽陽性です。レコードにfoobarが含まれていて、barではなく、それでも一致します。

この入力例では、シンプルなソリューションを投げるでしょう:

TAGDESCRIPTIONS foo 
TAGS   blah 
TAGDESCRIPTIONS example 
TAGS   tmp 
TAGS   line 
TAGS   foobar 
TAGS   barfoo 
TAGDESCRIPTIONS bar and more words 
TAGS   com 
TAGS   foo 

は含むfoo、タグfooとタグの説明や複数の単語でのタグの記述があります。

我々は、検索文字列に説明以外の各要素を比較し、改行でレコードを分割してすべてを修正することができ:

bar and more words 

もたらす

awk ' 
BEGIN { RS = "TAGDESCRIPTIONS *" } 

{ 
    # Split record at newlines, store in arr 
    split($0, arr, "\n") 

    # Skip first element (description), compare to 'foo' 
    for (i = 2; i <= length(arr); ++i) { 
     if (arr[i] ~ " +foo$") { 

      # Matches - print description 
      print arr[1] 

      # No need to look at the rest of the record 
      break 
     } 
    } 
}' infile 

正確には、マルチ文字レコードセパレータとlength関数のため、GNU awkです。

+1

マルチキルRSと 'length(array)'のためにgawk固有のことを言及する必要があります。 –

0

私はそれを撃つでしょう。
私はgrepやawkについては分かりませんが、以下はPCREスタイルの先読みとインライン修飾子グループを使用する生の正規表現
です。

(?ms) 
^ TAGDESCRIPTIONS \s+ 
(\w*)      # (1) 
\s+ 
(?: 
     (?!^TAGDESCRIPTIONS) 
     . 
)+ 
^ TAGS \s+ foo 

を拡大

(?ms)^TAGDESCRIPTIONS\s+(\w*)\s+(?:(?!^TAGDESCRIPTIONS).)+^TAGS\s+foo

あなたが必要とbar単語は正規表現からキャプチャグループ1肉です。それは主に特定の行をフィルタリングするためであるとして

出力

** Grp 0 - (pos 68 , len 83) 
TAGDESCRIPTIONS bar 
TAGS   com      
TAGS   foo 
** Grp 1 - (pos 84 , len 3) 
bar 
2
$ awk '/TAGDESCRIPTIONS/{d=$2} /foo/{print d}' file 
bar 
関連する問題