Assuming you have two CSV files as follows:
$ 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
You may use Miller (mlr
) to join the two files on the common field Chr_Name
, filter the resulting data by extracting only the records that have a position
field that fall between start_pos
and end_pos
, and then finally cut the unwanted position
field from the data.
$ 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
The mlr
command, nicely formatted:
mlr --csv \
join -f file2 -j Chr_Name then \
filter '$start_pos <= $position && $position <= $end_pos' then \
cut -x -f position \
file1
With the same two files as above, but using SQLite3 with an in-memory database as suggested by Marcus Müller in comments:
$ 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
The SQLite3 statements:
.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
The dotted commands imports the two files into the tables file1
and file2
while the SELECT
statement performs the actual query.
sqlite3
would make this significantly easier, and if your data is large, faster