XXXX という文字列を含んだファイルを探すための、もうひとつのやりかた
find してからの xargs grep -n のほうが便利ではあるけど、ファイル名だけがほしい場合というのもある。
find の -exec 節は、コマンドの終了ステータスで真偽が決まる。
grep の終了ステータスはマッチすれば 0 を返すから、そのマッチしたファイルは -print アクションに進み、出力される。
$ find "${DIR}" -type f -exec grep -m1 -s -F "XXXX" {} \; -print
[追記] --files-with-matches / -l オプションのほうがいいのかも
$ find "${DIR}" -type f | xargs grep -l -F "XXXXX"
範囲を生成するようなあれ(パース編)
きのうのつづきで範囲構文を解析することにする。
パーサはさくっと構文解析ライブラリにまかせる。
python パーサ
で検索しただけだけど、BNF っぽく書けることで雑に採用。
もっとも BNF がこれでいいのかは自信がないが、doctest が通ってるしいいことにしよう。
$ sudo easy_install pip $ sudo pip install lark-parser
チュートリアルを眺めつつ、こんなかんじで書けた。
#!/usr/bin/env python # coding: utf-8 ''' >>> list(parse("1")) [1] >>> list(parse("1,2")) [1, 2] >>> list(parse("1,2,5-7")) [1, 2, 5, 6, 7] >>> list(parse("1,2,5-7,9-10,13")) [1, 2, 5, 6, 7, 9, 10, 13] ''' import itertools from lark import Lark, Transformer, v_args @v_args(inline=True) class RangeSyntax(Transformer): concat = itertools.chain def constant(self, x): return itertools.repeat(int(x), 1) def range(self, start, end): return xrange(int(start), int(end) + 1) parser = Lark(''' ?expr : expr "," expr -> concat | NUMBER "-" NUMBER -> range | NUMBER -> constant %import common.NUMBER %import common.WS %ignore WS ''', start='expr', parser='lalr', transformer=RangeSyntax()) parse = parser.parse if __name__ == '__main__': import doctest doctest.testmod()
範囲を生成するようなあれ
crontab の構文で "1-10,15,16" みたいなやつがあるけど、これを解析してイテレータがでてきたら便利そうである。
上の場合、1 から 10 がでてきて、次に 15, 16 とでてくるようなイテレータが生成される。
#!/usr/bin/env python # coding: utf-8 from itertools import repeat, chain def once(x): return repeat(x, 1) def main(): expected = [1,2,3,4,5,6,7,8,9,10,15,16] actual = chain(xrange(1, 11), once(15), once(16)) assert expected == list(actual) if __name__ == '__main__': main()
こういうのを生成できるパーサをでっち上げる瞬発力がほしい。