我有个问题。我试图自己处理它,但似乎我太新了awk
,无法让它发挥作用。
假设我们有一个文件(例如 database.txt)(值以制表符分隔):
NA64715 YU24921 MI84612 MI98142 NA94732
3241531 4957192 4912030 6574918 0473625
0294637 9301032 8561730 8175919 8175920
9481732 9359032 8571930 8134983 9385130
9345091 9385112 2845830 4901742 3455141
Run Code Online (Sandbox Code Playgroud)
在一个单独的文件(例如populations.txt
)中,我有关于哪个 ID 属于哪个组的信息,例如:
NA64715 Europe
YU24921 Europe
MI84612 Asia
MI98142 Africa
NA94732 Asia
Run Code Online (Sandbox Code Playgroud)
我需要做的是强制awk
为所有组(欧洲、亚洲、非洲)创建带有列的单独文件。我需要处理的文件很大,所以我不能简单地计算和编号列并用简单的方法来完成。我需要awk
检查哪个 ID 属于哪个人口(欧洲等),然后在数据库文件中找到该特定列,然后将整个列复制到一个新文件(所有人口分开)。
结果应如下所示:
文件 1 ( europe.txt
):
NA64715 YU24921
3241531 4957192
0294637 9301032
9481732 9359032
9345091 9385112
Run Code Online (Sandbox Code Playgroud)
档案 2 ( asia.txt
)
MI84612 NA94732
4912030 0473625
8561730 8175920
8571930 9385130
2845830 3455141
Run Code Online (Sandbox Code Playgroud)
文件 3 ( africa.txt
)
MI98142
6574918
8175919
8134983
4901742
Run Code Online (Sandbox Code Playgroud)
谁能帮我解决这个问题?
这在一次通过文件时起作用,并且不需要将整个文件存储在内存中。它确实为每个目标文件保留了打开的文件描述符。
awk -F '\t' '
NR==FNR {population[$1]=$2; next}
FNR==1 {
for (i=1; i<=NF; i++) {
destination[i] = population[$i] ".txt"
}
}
{
delete separator
for (i=1; i<=NF; i++) {
printf "%s%s", separator[destination[i]], $i > destination[i]
separator[destination[i]] = FS
}
for (file in separator) {
printf "\n" > file
}
}
' populations.txt database.txt
Run Code Online (Sandbox Code Playgroud)
我相信这不是最好的方法,因为我们需要读取database.txt的次数与我们拥有的区域加一一样多。不幸的是,我没有想到另一种方式。
转置数据库.txt:
awk '{for(i=1;i<=NF;i++){a[NR,i]=$i}}NF>p{p=NF}END{for(j=1;j<=p;j++ ){str=a[1,j];for(i=2;i<=NR;i++){str=str" "a[i,j];}print str}}' 数据库.txt > 数据库.tmp
更具可读性(相同的命令):
awk '
{
for (i=1; i<=NF; i++) {
a[NR,i] = $i
}
}
NF>p { p = NF }
END {
for(j=1; j<=p; j++) {
str=a[1,j]
for(i=2; i<=NR; i++){
str=str" "a[i,j];
}
print str
}
}' database.txt > database.tmp
Run Code Online (Sandbox Code Playgroud)
2.读取带有ids的文件并从转置的database.tmp中grep所有id:
while read id region ; do grep -m 1 $id database.tmp >> $region.txt.tmp ; done < population.txt
Run Code Online (Sandbox Code Playgroud)
3.将所有region.txt.tmp文件转置为您需要的形式:
for region_file in *txt.tmp ; do awk '{for(i=1;i<=NF;i++){a[NR,i]=$i}}NF>p{p=NF}END{for(j=1;j<=p;j++){str=a[1,j];for(i=2;i<=NR;i++){str=str" "a[i,j];}print str}}' $region_file > ${region_file%.tmp} ; done
Run Code Online (Sandbox Code Playgroud)
4.删除所有临时文件