Bashでは、他のファイルの2つの値に基づいて1つのCSVファイル行を調整します。

Bashでは、他のファイルの2つの値に基づいて1つのCSVファイル行を調整します。

2つのCSVファイルがあります。

  • 1つは長い列です:Chr_Name、、、、、、。hjstart_posend_pos
  • もう一つは熱とChr_Nameposition

Chr_Name最初のファイルに基づいて最初のファイルの行をフィルタリングし、最初のファイルの先頭と最後の間の位置に基づいて行をフィルタリングする必要があります。

どうすればいいですか?

例:

  • ファイル1:
    Chrk, 10, 20,  1010, 1025
    Chrk, 20, 10, 1020, 1040
    ChrM, 10, 10, 50, 120
    
  • ファイル2:
    Chrk, 1030
    ChrM, 70
    
  • 必須出力ファイル:
    Chrk, 20, 10, 1020, 1040
    ChrM, 10, 10, 50, 120
    

ベストアンサー1

次の2つのCSVファイルがあるとします。

$ cat file1
Chr_Name,h,j,start_pos,end_pos
Chrk,10,20,1010,1025
Chrk,20,10,1020,1040
ChrM,10,10,50,120
$ cat file2
Chr_Name,position
Chrk,1030
ChrM,70

あなたはそれを使用することができますミラーmlr)到着参加する共通フィールドに2つのファイルChr_Nameフィルターpositionとfinallyの間のフィールドを持つレコードのみを抽出してstart_pos結果データを取得します。end_pos切るpositionデータに不要なフィールドがあります。

$ mlr --csv join -f file2 -j Chr_Name then filter '$start_pos <= $position && $position <= $end_pos' then cut -x -f position file1
Chr_Name,h,j,start_pos,end_pos
Chrk,20,10,1020,1040
ChrM,10,10,50,120

コマンドmlrの形式は次のとおりです。

mlr --csv \
    join -f file2 -j Chr_Name then \
    filter '$start_pos <= $position && $position <= $end_pos' then \
    cut -x -f position \
    file1

上記と同じ2つのファイルを使用しますが、SQLite3とメモリ内データベースを使用します。Marcus Müllerがコメントで提案したように:

$ sqlite3 :memory: '.mode csv' '.headers on' '.import file1 file1' '.import file2 file2' 'SELECT file1.* FROM file1 JOIN file2 ON (file1.Chr_Name = file2.Chr_name) WHERE CAST(position AS INTEGER) BETWEEN start_pos AND end_pos'
Chr_Name,h,j,start_pos,end_pos
Chrk,20,10,1020,1040
ChrM,10,10,50,120

SQLite3ステートメント:

.mode csv
.headers on
.import file1 file1
.import file2 file2

SELECT file1.* FROM file1
    JOIN file2 ON (file1.Chr_Name = file2.Chr_name)
    WHERE CAST(position AS INTEGER) BETWEEN start_pos AND end_pos

ダッシュコマンドは両方のファイルをテーブルにインポートし、file1ステートメントfile2SELECT実際のクエリを実行します。

おすすめ記事