私は以下からインスピレーションを得て、ファイルセット内のすべてのSQL文をawk
見つけるために範囲パターンを使用しようとしています。select
このstackoverflowの答え。
awk
マニュアルから:
表現の形を
pattern1, pattern2
指す。範囲モード。一致するレコードで始まり、pattern1
一致するレコードをpattern2
含むすべての入力レコードを一致させます。
私の最初の試みは
awk '/select/,/from/' *
この場合、*
さまざまなファイルがたくさん表示されます。
これにより、select
HTMLタグに誤ったヒットが返されたため、次のようにコマンドを改善しました。
awk '/[^<]select[^>]/,/from/' *
これにより、ほとんどのクリックが削除されるようです。
ただし、コメントに「select」という単語が表示されるため、まだいくつかの誤ったヒットが発生し、これらのヒットは、「from」の最後のヒットまたはファイルの終わりより前の各ヒットから多くのラインノイズにつながります。私が望むのは、「select」と「from」の間に10行以上がある場合、範囲パターンが一致を登録しないことです。
pattern1
私の質問は:一致と一致の間の行数が指定されたしきい値をpattern2
超えると、範囲パターンが一致しないようにすることはできますか?では、どうすれば達成できますか?
答え1
スコープモードは便利ですが、柔軟性はありません。これを使用しないで、代わりに変数間または変数間の状態を維持してください。 awkスクリプト/select/,/from/
は次のとおりです。
/select/ {printing = 1}
printing {print}
/from/ {printing = 0}
範囲を複数の行に制限するには、表示された行のカウンタを保持し、表示するかどうかを判断するまで出力を累積します。
/select/ {select_text = $0; select_line_count = 1;}
select_line_count {select_text = select_text "\n" $0}
/from/ {if (select_line_count <= 10) {print select_text; print}
select_line_count = 0}
select
行の先頭(スペースを除く)に含める必要があり、その後にスペースが続くようにパターンを最適化する必要があります。/^[\t ]*select($|[\t ])/
答え2
/pattern1/,/pattern2/
{}
このような状況が発生した場合は、実行するブロックを追加して必要に応じて条件を拡張できます。
たとえば、50から70の数字を印刷しながら、各ブロックの最初の5つの一致のみを印刷する方法を見てみましょう。
$ seq 200 | awk '/50/,/70/ {if ($0~/50/) {c=0}; if (c++ <= 5) print}'
50
51
52
53
54
55
150
151
152
153
154
155
あなたの場合は、次のように言いたいことがあります。これにより、一致する最初の10行が印刷されます。
awk '/[^<]select[^>]/,/from/ {if (c++ <= 10) print}' *
より複雑な解決策は、これらすべての出力を保存してEND
ブロックに印刷することです。これにより、特定の行だけでなくブロック自体も制御できます。データを配列などに保存します。