AWK で grep を作る     Last modified: Mar 02, 2004

自分で作ると,完全なものはできないが,小回りの利いたものを作ることはできる。

使用法
MacGREP パターン オプション -- 対象ファイル

MacGREP のある場所に注意。
パスを通しておくか,明示的に指定するか。
chomod 755 MacGREP などとして,実行可能にしておくこと。


~/MacGREP file|the -b 2 -a 1 -l -- test.txt

パターンは最初のパラメータとして指定(gawk の正規表現が使える)
例では,file または the を含む行の前2行,後1行を行番号をつけて表示する

オプション

-b xx    一致行の前の xx 行も表示(xx <= 100) 
-a xx    一致行の後の xx 行も表示
-l       行番号をつけて表示
-c       一致行数のみを表示
-- の後が対象ファイルの指定

特殊な仕様
一致行の後の表示を指定したとき,そこにパターンが含まれるときにはその一致行移行の n 行を表示することはない(再帰的ではない) 最初に全テキストを入力して保存しておくというアルゴリズムを使えば可能だが...
--- 次行からスクリプト開始 --- #!/usr/local/bin/jgawk -f # MacGREP 0.1 S. AOKI, Nov 11, 1996 # MacGREP 0.2 S. AOKI, Mar 02, 2004 BEGIN { pattern = ARGV[1] for (i = 1; i < ARGC; i++) { if (ARGV[i] == "--") { for (j = 1; j <= i; j++) { ARGV[j] = "" } break; } else if (ARGV[i] == "-l") { line_number++ } else if (ARGV[i] == "-c") { count_only++ } else if (ARGV[i] == "-b") { before = (ARGV[i+1] > 100) ? 100 : ARGV[i+1] ARGV[i+1] = "" } else if (ARGV[i] == "-a") { after = ARGV[i+1] ARGV[i+1] = "" } } } FNR == 1 { initialize() } { sv() } $0 ~ pattern { count++ if (!count_only) { if (before) { print "" for (i = nsaved-before; i < nsaved; i++) { list(i, saved[i]) } } list(FNR, $0) if (after) { for (i = 1; i <= after; i++) { if (getline <= 0) { break } else if (FNR == 1) { initialize() } sv() list(FNR, $0) } if (!before) { print "" } } } } function initialize( i) { count_out() nfiles++ count = 0 nsaved = 0 for (i in saved) { delete saved[i] } printf "\n***** %s *****\n\n", FILENAME prev_file = FILENAME } function sv() { nsaved++ if (nsaved > 100) { delete saved[nsaved-100] } saved[nsaved] = $0 } function list(i, str, mark) { if (i) { mark = ((after || before) && str ~ pattern ) ? "*" : " " if (line_number) { printf "%s%5i %s\n", mark, i, str } else { print str } } } function count_out() { if (count_only && nfiles) { print prev_file ": " count, "counts" } } END { count_out() } --- 前行でスクリプト終了 ---


-a xx を指定したとき,一致行以降の xx 行にパターンが含まれるとき,最後に現れた一致行からさらに xx 行を表示させるためには,3 行追加すればいいですね。

if (after) {
        for (i = 1; i <= after; i++) {
                if (getline <= 0) {
                        break
                }
                else if (FNR == 1) {
                        initialize()
                }
                sv()
                list(FNR, $0)
                # 3行追加  '96/11/12
                if ($0 ~ pattern) {
                        i = 0
                }
                # ここまでの3行
        }
        if (!before) {
                print ""
        }
}


・ 直前のページへ戻る  ・ E-mail to Shigenobu AOKI