grep パターンとファイルのペア

grep パターンとファイルのペア

他のtxtファイルのリストから検索したいパターンのリストを含むファイル(search.patterns)があります。

検索モード

home
dog 
cat

ファイル1.txt

home 3
tiger 4
lion 1

ファイル2.txt

dolphin 6
jaguar 3
dog 1

ファイル3.txt

donkey 3
cat 4
horse 1

だから、file1でパターンファイルの最初の行、file2から2行目、file3から3行目を検索したいと思います。

出力:

home 3
dog 1
cat 4

私は次のようなコードを書いた。

for f in *.txt;
    do 
    while IFS= read -r LINE; 
        do grep -f "$LINE" "$f" > "$f.out"
    done < search.patterns
done

しかし、出力ファイルは空です。

どんな助けでも大変感謝します。ありがとうございます。

答え1

GNU awk()を使用すると、入力ファイルが変更されるたびにルールをgawk使用して新しいパターンを読み取ることができます。BEGINFILE

$ gawk 'BEGINFILE{getline pat < "search.patterns"} $0 ~ pat' file\ {1..3}.txt
home 3
dog 1
cat 4

getlineたとえば、新しいモードが返されることを実際に確認する必要があります。

gawk '
  BEGINFILE {
    if((getline pat < "search.patterns") <= 0) {
      print "Error reading pattern" > "/dev/stderr"
      exit 1
    }
  } 
  $0 ~ pat
' file\ {1..3}.txt

ちなみにawkパターンは拡大するgrepwith オプション-Eがサポートする式に似た正規表現です。

最初のファイルに渡して適切に使用して、パターンをインデックス配列として読み取るか、配列内の次のパターンを見つけることで、awk非GNUでも同じ効果を得ることができます。search.patternsNRFNR

答え2

使用bash:

#!/bin/bash

files=( 'file 1.txt' 'file 2.txt' 'file 3.txt' )

while IFS= read -r pattern; do
    grep -e "$pattern" "${files[0]}"
    files=( "${files[@]:1}" )
done <search.patterns

テストしてみてください:

$ bash script.sh
home 3
dog 1
cat 4

スクリプトは関連ファイル名をfiles配列に保存し、ファイルsearch.patternsからパターンを読み取ります。各パターンについて、filesリストの最初のファイルが照会されます。その後、処理されたファイルはリストから削除されますfiles(結果として、リストの最初の最初のファイル名が生成されます)。

パターン数がのファイル数を超えるとfilesエラーが発生しますgrep

答え3

pasteこのパターンを使用してファイルを一致させることができます。

paste <(printf "%s\n" *.txt) search.patterns | while IFS=$'\t' read -r file pattern; do
    grep -- "$pattern" "$file"
done

ファイル名にタブ文字が含まれていないとします。

関連情報