ファイルBをAと比較し、awk、sed、またはgrepを使用してAからデータを抽出します。

ファイルBをAと比較し、awk、sed、またはgrepを使用してAからデータを抽出します。

ファイルAにはすべてのデータが含まれ、他のファイルBにはIDのみが含まれる2つのファイルがあります。私が望むのは、ファイルBをファイルAと比較し、そのIDのデータを取得することです。私はSUSE Linuxを使用しています。

ファイルA

C    02020 Two-component system [PATH:aap02020]
D      NT05HA_1798 sensor protein CpxA  
D      NT05HA_1797 CpxR K07662 cpxR
C    02030 *Bacterial chemotaxis* [PATH:aap02030]
D      NT05HA_0919 maltose-binding periplasmic protein
D      NT05HA_0918 maltose-binding periplasmic protein 
C    03070 *Bacterial secretion system* [PATH:aap03070]
D      NT05HA_1309 protein-export membrane protein SecD 
D      NT05HA_1310 protein-export membrane protein SecF 
D      NT05HA_1819 preprotein translocase subunit SecE
D      NT05HA_1287 protein-export membrane protein  
C    02060 Phosphotransferase system (PTS) [PATH:aap02060]
D      NT05HA_0618 phosphoenolpyruvate-protein 
D      NT05HA_0617 phosphocarrier protein HPr 
D      NT05HA_0619 pts system 

文書B

Bacterial chemotaxis
Bacterial secretion system

希望の出力:

C    02030 *Bacterial chemotaxis* [PATH:aap02030]
D      NT05HA_0919 maltose-binding periplasmic protein
D      NT05HA_0918 maltose-binding periplasmic protein 
C    03070 *Bacterial secretion system* [PATH:aap03070]
D      NT05HA_1309 protein-export membrane protein SecD
D      NT05HA_1310 protein-export membrane protein SecF
D      NT05HA_1819 preprotein translocase subunit SecE  
D      NT05HA_1287 protein-export membrane protein  

答え1

あなたが使用できるawk

awk 'NR==FNR{         # On the first file,
       a[$0];         # store the content in the array a
       next
     } 
     {                        # On the second file, 
         for(i in a)          # for all element in the array a,
            if(index($0,i)) { # check if there is match in the current record
               print "C" $0   # in that case print it with the record separator
               next
            }
     }' fileB RS='\nC' fileA
C    02030 *Bacterial chemotaxis* [PATH:aap02030]
D      NT05HA_0919 maltose-binding periplasmic protein
D      NT05HA_0918 maltose-binding periplasmic protein 
C    03070 *Bacterial secretion system* [PATH:aap03070]
D      NT05HA_1309 protein-export membrane protein SecD 
D      NT05HA_1310 protein-export membrane protein SecF 
D      NT05HA_1819 preprotein translocase subunit SecE
D      NT05HA_1287 protein-export membrane protein  

答え2

C <word>との間の部分を正確に一致させたい場合[PATH:...](そして*サンプルの部分は実際のデータの一部ではなく強調のためのものであると仮定)、次のことができます。

awk '
  !start {all_strings[$0]; next}
  /^C/ {
    key = $0

    # strip the leading C <word>:
    sub(/^C[[:blank:]]+[^[:blank:]]+[[:blank:]]*/, "", key)

    # strip the trailing [...]:
    sub(/[[:blank:]]*\[[^]]*][[:blank:]]*$/, "", key)
    selected = key in all_strings
  }
  selected' fileB start=1 fileA

信頼性を向上させることに加えて、ファイルを一度だけ読み取る(たとえば、 Bacterial secretion1つのレコードのみが一致、Bacterial secretion一致しないBacterial secretion system)、一致は多くの部分文字列検索や正規表現の一致ではなくハッシュテーブルの検索であるため、非常に効率的です。

答え3

ループを使用すると倒れると確信していますが、それでも...ここに1つのアプローチがあります。

#!/bin/bash

while read -r line; do
        sed -n "/$line/,/^C/p" fileA | sed '$d'
        done < fileB

例:

./bacteria.sh 
C    02030 *Bacterial chemotaxis* [PATH:aap02030]
D      NT05HA_0919 maltose-binding periplasmic protein
D      NT05HA_0918 maltose-binding periplasmic protein 
C    03070 *Bacterial secretion system* [PATH:aap03070]
D      NT05HA_1309 protein-export membrane protein SecD 
D      NT05HA_1310 protein-export membrane protein SecF 
D      NT05HA_1819 preprotein translocase subunit SecE
D      NT05HA_1287 protein-export membrane protein  

サンプルファイルはどこにありますかfileAfileB

正規表現分析:

sed -n "/$line/,/^C/p" fileA | sed '$d'

$line文字で始まる行と次の行の間の行を印刷しますC。ただし、sed '$d'最後の行は「停止表示」の役割のみするので除外( )します。


sed --version
sed (GNU sed) 4.2.2

bash --version
GNU bash, version 4.2.46(1)-release (x86_64-redhat-linux-gnu)

答え4

データは新しい行で始まるレコードfileAに分割されます。各レコードは、新しい行で始まるinteフィールドCに分割されます。D

行を読み取り、fileBそれを使用して各レコードの最初のフィールドを照会する必要がありますfileA

while read -r query; do
    awk -vq="$query" 'BEGIN { RS="^C|\nC"; FS=OFS="\nD" } $1 ~ q {print "C" $0}' fileA
done <fileB

行の先頭のどこにでもRS一致するようにレコード区切り記号()を設定しました。Cまたは改行文字の後にある場合、最初のレコードのどの項目も正しく一致しない可能性があります。awk変数を使用してqファイルから読み取った値を保持し、各レコードの最初のフィールドをその値と一致させます。

結果:

C    02030 *Bacterial chemotaxis* [PATH:aap02030]
D      NT05HA_0919 maltose-binding periplasmic protein
D      NT05HA_0918 maltose-binding periplasmic protein
C    03070 *Bacterial secretion system* [PATH:aap03070]
D      NT05HA_1309 protein-export membrane protein SecD
D      NT05HA_1310 protein-export membrane protein SecF
D      NT05HA_1819 preprotein translocase subunit SecE
D      NT05HA_1287 protein-export membrane protein

関連情報