2018/05/17

grepを使った絞り込み ファイル単位で複数の行に条件を設けて抽出する場合


grepを使った絞り込み

条件

ディレクトリA
   aaa.xml
   bbb.xml
   ccc.xml
   ・
   ・
   ・
   zzz.xml

aaa.xml
<type>0</type>
   ・
   ・
<name>0463</name>

bbb.xml
<type>1</type>
   ・
   ・
<name>0463</name>

ccc.xml

<type>2</type>
   ・
   ・
<name>1234</name>

ccc.xml
<type>0</type>
   ・
   ・
<name>0463</name>


ディレクトリAの中にあるxmlで、typeが0、nameが0463のファイルを抽出したい場合
一回のgrepで抽出しようとしたが、行が異なると判定されてしまうので、上手くいかず。
-P '検索箇所頭[\s\S]*?検索箇所末尾' の Pオプションを使った場合、
ファイルサイズが大きく、ファイス数が多いとかなりの負荷がかかる。
また、改行の\nを削除したファイルに置換するものコピーの手間がかかる。
今回の対象ファイル数が、25,000ファイル位あった。
こんなの一つづつはご免蒙る。


そこで、次の手順を取った。
1.取得したい条件を一旦ファイルにする。
 $ grep -r -l "0" /ディレクトリA >type.txt
 $ grep -r -l "0463" /ディレクトリA >name.txt

-rで回帰
-l でファイル名のみ抽出させる。(行数やパターンが出ると、2でgrepした際に重ならない)

2.grepで重なる部分を取得する。
 $ grep -f {type,name}.txt
 結果
 aaa.xml
 ccc.xml
  ・
  ・
 のように抽出したいファイルが絞り込める。
 実際は、
 /home/ディレクトリA/ディレクトリB_1000/1/20180301_134814.xm ディレクトリBのレベルで判別したいので、一旦マージ用のファイルを生成し、
 $ grep -f {type,name}.txt >merge.txt

この段で、P オプションとoオプション(only-matching)を使って絞り込む
  $ grep -oP 'ディレクトリB[\s\S]*?/' merge.txt | uniq -d
ディレクトリB/ ←この部分を取得したい。
 uniq -d  ユニークで重複を表示させない。
  結果
 ディレクトリB_1000
 ディレクトリB_1010
 ディレクトリB_1012
    ・
    ・
    ・
 ディレクトリ
期待値が取れた。 

0 件のコメント:

コメントを投稿