grepで大量の条件がある場合の対処方法
1.概要
grepで抽出処理を良く実行します。条件が1個や2個ならば良いのですが、大量の条件がある場合にどうやって実現すると良いか悩みました。forのループで処理できるのはわかるのですが、効率が悪いので方式を検討しました。その内容を記述します。
条件が1つの場合: grep 0001 test.file
条件が2つの場合: grep -e 0001 -e 0002 test.file
2.詳細
forのループを作成して、条件の文字列を作ります( cond.txt )。
条件文字列作成のforのループは文字列を検索しないので効率には影響しません。
-e 0001 -e 0002 -e 0003 -e 0004 -e 0005 ... -e 1000
調べたい対象ファイルをtest.fileとします。
COND=$(cat cond.txt)
grep ${COND} test.file
3.所見
CONDの長さに制限があると思ったので調べてみました。
getconf ARG_MAX
2097152
十分なサイズだと思いますが、実際に試験しようと思っています。
4.追加
(1) grepで非常に大量の条件がある場合の対処方法
実際にgrepで大量のパラメータを設定してみると下記エラーになりました。
grep: Argument list too long
調べてみるとエラーの条件が想定したものと異なりました。その内容を記述します。
(a) パラメータが長すぎる
STR="-e 100001 -e 100002 -e 100003 -e 100004 -e 100005 ... -e 300000"
を作成して、下記grepを実行するとgrep: Argument list too longとなりました。
grep ${SRT} test.txt > test.out
参考資料によるとパラメータの長さが1MBを超えたことが要因のようです。
この対策が下記(b)のケースと同じに見えるので、対処方法を見つけることが難しかった。
次回はそれに関して記述します。
(b) test.txtが大きすぎる
text.txt程度では起きることはありません。
しかし、参考資料に記載されているように検索対象が多すぎる場合も同じエラーになるようです。
grep: Argument list too longと表示されて判別が難しいと思います。
検索対象が多すぎる場合は、参考資料に対処方法が記載されており、xargsを利用して分割します。
(2) grepで非常に大量の条件がある場合の抜本改善策
実際にgrepで大量のパラメータを設定して、下記エラーが発生しました。
grep: Argument list too long
この対策に関して記述します。
grep --help を参照すると下記指定ができます。
-f, --file=FILE take PATTERNS from FILE
そこで、pattern.datを以下のように作成します。
100001
100002
100003
100004
100005
...
300000
grep -f pattern.dat test.txt > test.out
を実行するとgrep: Argument list too longは解消されます。
考察
grepは正規表現が可能なので、少し調べてみました。
pattern.datを少し変えてみました。
^[0-9]*,100001
^[0-9]*,100002
...
^[0-9]*,300000
同じように実行すると途中でエラーとなります。
grep -f pattern.dat test.txt > test.out
調べてみるとメモリを使い切って、処理を中断していました。
-f で指定する場合は、正規表現を多数記述するのは難しいようです。
コメント
コメントを投稿