我有两个文件 A 和 B。文件 A 有 4 列和 600,000 行。文件 B 有 4 列和 5000 行。例子:
文件-A:
ENSB1 1 12245 0.53 0.002
ENSB2 1 13400 0.27 0.0003
ENSB3 1 14780 0.13 0.00001
ENSB4 1 15201 0.33 0.9
ENSB5 2 56259 0.70 0.0002
ENSB6 2 57000 0.42 0.00004
ENSB7 2 58200 0.50 0.5
文件-B:
1 12000 15000 G1
1 14000 16000 G2
2 56000 59000 G3
我想选择 File-B 的第一行。然后,我想以文件 A 第 3 列中的值落在文件 B 第 2 列和第 3 列中的值范围内的方式识别文件 A 中的多行;文件 A 第 2 列中的对应值也与文件 B 第 1 列中的值匹配。我期望 File-A 中的多行满足上述条件。一旦通过上述标准识别出多行,则在文件 A 的这些行中选择第 5 列中的最低值,并将其写入文件 B 中相应行的新列中。对 File-B 中的所有行一一重复这些步骤。
预期新文件:
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004
我是学习 Linux 命令的新手,如果有人能提供帮助,那就太好了。
答案1
尝试
awk 'NR==FNR {Line[FNR] = $0 # first file processing
Cat[FNR] = $1
Min[FNR] = $2
Max[FNR] = $3
Low[FNR] = 1E10 # initialize to high number so first value from file2 will be lower
ML = FNR
next
}
# second file processing; if same Category and $3 between Min and Max, and $5 lower than before one, keep $5
{for (i=1; i<=ML; i++) if ($2 == Cat[i] &&
$3 >= Min[i] &&
$3 <= Max[i] &&
$5 < Low[i]) Low[i] = $5
}
END {for (i=1; i<=ML; i++) print Line[i], Low[i]
}
' File-B File-A
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004
不需要太多解释:从第一个文件 ( NR == FNR
) 开始,它保留类别和范围/边界值,并设置 Low 数组元素,以便第一个读取的实际值较低。处理第二个文件时,它会循环遍历上述记录的数据集。如果新读取的记录与条目具有相同的类别,并且 $3 在 Min 和 Max 之间,并且 $5 比之前获得的记录低,则将 $5 保留在数组中Low
。在该END
部分中,将记录的行及其获得的Low
值打印到标准输出。
答案2
使用任何awk
和任何sort
:
$ cat tst.sh
#!/usr/bin/env bash
sort -k5,5n -- "$1" |
awk '
NR==FNR {
if ( !($3 in map) ) {
keys[++numKeys] = $3
map[$3] = $5
}
next
}
{
for ( k=1; k<=numKeys; k++ ) {
key = keys[k]
if ( ($2 <= key) && (key <= $3) ) {
print $0, map[key]
next
}
}
}
' - "$2"
$ ./tst.sh 'File-A' 'File-B'
1 12000 15000 G1 0.00001
1 14000 16000 G2 0.00001
2 56000 59000 G3 0.00004
当出现重复的 $3 值时,上面将正确使用最低的关联 $5 File-A
。