パターンの横または下にある単語を見つける必要があります。

パターンの横または下にある単語を見つける必要があります。

次の行を含むファイルがあります。

    .......... FROM ABCD_EXT
    .......... FROM HEG_EXT1 
.......... from
           xyz_EXT
.......... FROM abd_EXT2 
..........where QWT_EXT.SID=POI_EXT.GET
..........where QWT_EXT.SID=POI_GET.END_EXT

「FROM」(大文字と小文字を区別しない)の横または下にあり、_EXTで終わる単語をgrepします。

つまり、予想される出力は次のようになります。

ABCD_EXT 
xyz_EXT

編集:はい、同じ行に表示されるか、次の行に表示されるか、「from」の後の次の単語をgrepする必要があります。

私はこれを試して最初の部分を正しく得ました(同じ行)。

grep _EXT rt.sql |grep -i from|sed -e 's/_EXT/_EXT /g'|awk '{print $NF}'|grep _EXT

下の行から単語を取得するのは問題です。

答え1

そしてpcregrep

pcregrep -Mo1 '(?<!\S)(?i:from)\s+(\S*_EXT)(?!\S)' < rt.sql
  • -MM複数行モードの場合
  • -o1最初のキャプチャoグループと一致するコンテンツを出力します。1
  • \sスペース文字(少なくともスペース、タブ、CR、およびLFを含む)と一致し、スペース以外の\S文字と一致します。
  • x+:1つ以上のxsと一致
  • x*:0個以上のxsと一致します。
  • (?i:from)from、、大文字と小文字を区別せず、と同じです[fF][rR][oO][mM]
  • (?<!\S): 空白でない場合、またはIOWの否定的な振り返り前提は、前の内容が空ではないということです。(スペースやトピックの先頭にも同じことが当てはまります)。
  • (?!\S):同じですが、後ろではなく前を見てください。 SQLなら、;許可したいかもしれません。(?![^\s;])

そのエントリがない場合は、pcregrep(の最初のエントリperl)を使用してファイル全体を延期できます。ppcregrep-0777

perl -l -0777 -ne 'print for /(?<!\S)(?i:from)\s+(\S*EXT)(?!\S)/g' < rt.sql

あるいは、GNUを使用してgrepPCREサポートで構築されている場合(これは-PPerlなどの正規表現を一致させるためのオプションを追加します):

grep -zPo '(?<!\S)(?i:from)\s+\K\S*EXT(?!\S)' < rt.sql | tr '\0' '\n'

GNUは最初のキャプチャグループ一致の印刷をgrepサポートしていないため、代わりに一致の内容全体を印刷しますが、一致で何をeepするかをマッチャーに伝えます。-o<n>n-o\KK

行ではなく NUL で区切られたレコードを処理するため、-z入力に NUL が含まれていないと仮定すると (通常は SQL とテキストの場合に該当する)、これはファイルの全内容を構成する 1 つのレコードになります。 Perlのように上記のフルルックパターン。ただし、出力レコード区切り文字もNULなので、tr各一致が別々の行になるように改行に変換する必要があります。

答え2

GNUの使用sed

$ sed -En 'N;s/.*from( ([^_]*_ext\>)[^\n]*\n.*|\n.* ([[:alpha:]]+_ext\>))/\2\3/Ip' input_file
ABCD_EXT
xyz_EXT

答え3

サンプルデータで試してくださいdatafile

> awk -v printfirst=0 'BEGIN {IGNORECASE=1}
                       {if (printfirst == 1) {
                           print $1; printfirst=0; next
                                             }
                       } 
                       {for (i=1;i<=NF;i++) 
                           if ($i ~ /^from$/) {
                               if (i == NF) {printfirst=1} 
                               else if ($(i+1) ~ /_EXT$/) {print $(i+1)}
                           }
                       }' datafile

ABCD_EXT
xyz_EXT
> _

これを行う方法はいくつかありますawk(ここではAwkのGNUバージョンがあります)。私は便宜上、入力ファイルを2回解析するのを避けるためにこれを選択しました。

  • -vAwkに変数を渡すためのフラグです。変数をprintfirstゼロに初期化し、
  • BEGIN {IGNORECASE=1}Awk検索パターンで大文字と小文字を区別しないように設定する
  • 最初の{}ブロック:最初のAwkフィールドを条件付きで印刷します。つまり、レコード$1にジャンプします。next
  • 2番目のブロック{}:解析されたレコードfromの場合、大文字と小文字を区別せずに各フィールドを一致させようとします。
    • 一致するものがなければ、何もしません。
    • 一致する場合:
      • 一致するフィールドがレコードの最後のフィールドである場合は、awk内部変数をprintfirst1に設定して次のレコードに移動します。
      • 一致するフィールドがレコードの最後のフィールドでない場合は、レコードの次のフィールドを印刷します。

関連情報