Eu tenho um teste de arquivo com campos: cato e pos .
1 7100
1 35000
1 49321
1 49759
2 44842
2 52794
2 53558
3 53859
3 54013
3 55172
Eu tenho um arquivo db com os campos: cato , start e stop .
1 6408 8000
1 11822 16373
1 18716 23389
1 27690 34330
1 36552 39191
1 39313 44565
2 44839 50247
2 60987 65017
2 65705 71523
Meu objetivo é escolher linhas no arquivo db onde o campo pos
do arquivo test cai dentro do intervalo de início e parada do arquivo db . Existe a restrição de que a partida tenha que acontecer dentro de um grupo cato . Ambos os arquivos são classificados pelos campos 1 e 2. Como observação, ambos os meus arquivos reais também têm muitos outros campos.
Com este conjunto de dados de exemplo, meu resultado esperado seria:
1 6408 8000
2 44839 50247
Eu tenho um script que eu esmaguei.
k=1;
data_test=$(cat "test")
data_db=$(cat "db")
while read -r line
do
# helps to keep count of test rows
printf "$k \n"
# get cato
cato=$(echo $line | awk '{print $1}')
# get pos
pos=$(echo $line | awk '{print $2}')
# get number of chars in pos (to reduce number of lines awk needs to look through later)
pos_chr=$(echo -n $pos | wc -c)
# get lines in db that start with cato and pos chars match start or stop
matched=$(echo "$data_db" | grep -Ew "^$cato" | grep -Ew "[0-9]{$pos_chr}")
#echo "$db_cat"
# if matched is not empty
if [ ! -z "$matched" ]; then
# use awk to print lines in db where pos > start and pos < stop
echo "$matched" | awk -v apos='$pos' 'BEGIN{OFS="\t"}{if(apos >= $2 && apos <= $3) print $0}'
#check
#echo "$matched" | awk -v apos=$pos 'BEGIN{OFS="\t"}{print apos,$0}'
fi
((k=k+1))
done <<< "$data_test"
Parece awk
que não faz a comparação na última etapa. As coisas parecem funcionar até a última etapa e então não tenho certeza do que está errado. Talvez alguém veja o erro. Existe uma maneira melhor de fazer isso?
Com um único programa GNU
awk
(desdeGawk
v4.0):A saída:
Use
join
com um simplestest
:Você tem dados relacionais: os valores-chave em um arquivo correspondem aos valores-chave em outro, linha por linha.
join
é a ferramenta para reuni-los. Executejoin db test
e você notará que é o mesmo resultadoSELECT * FROM db JOIN test on test.cato=db.cato
se os dados estivessem em um banco de dados.Com isso em mãos, agora você tem linhas que colocam start, stop e pos em uma linha. Fazer um loop sobre eles, usando um
test
para verificar o intervalo, é fácil.