使用AWK将列附加到制表符分隔的文件
我有多个没有标题的文件,前四列相同,第五列不同。我必须使用awk将前四个公共列(所有第五列都有各自的标题)附加到单个最终制表符分隔的文本文件中,如下所示 文件1.txt使用AWK将列附加到制表符分隔的文件,awk,tab-delimited,Awk,Tab Delimited,我有多个没有标题的文件,前四列相同,第五列不同。我必须使用awk将前四个公共列(所有第五列都有各自的标题)附加到单个最终制表符分隔的文本文件中,如下所示 文件1.txt chr1 101845021 101845132 A 0 chr2 128205033 128205154 B 0 chr3 128205112 128205223 C 0 chr4 36259133 36259244 D 0 chr5 36259
chr1 101845021 101845132 A 0
chr2 128205033 128205154 B 0
chr3 128205112 128205223 C 0
chr4 36259133 36259244 D 0
chr5 36259333 36259444 E 0
chr6 25497759 25497870 F 1
chr7 25497819 25497930 G 1
chr8 25497869 25497980 H 1
文件2.txt
chr1 101845021 101845132 A 6
chr2 128205033 128205154 B 7
chr3 128205112 128205223 C 7
chr4 36259133 36259244 D 7
chr5 36259333 36259444 E 10
chr6 25497759 25497870 F 11
chr7 25497819 25497930 G 11
chr8 25497869 25497980 H 12
文件3.txt
chr1 101845021 101845132 A 41
chr2 128205033 128205154 B 41
chr3 128205112 128205223 C 42
chr4 36259133 36259244 D 43
chr5 36259333 36259444 E 47
chr6 25497759 25497870 F 48
chr7 25497819 25497930 G 48
chr8 25497869 25497980 H 49
预期输出文件Final.txt
Part Start End Name File1 File2 File3
chr1 101845021 101845132 A 0 6 41
chr2 128205033 128205154 B 0 7 41
chr3 128205112 128205223 C 0 7 42
chr4 36259133 36259244 D 0 7 43
chr5 36259333 36259444 E 0 10 47
chr6 25497759 25497870 F 1 11 48
chr7 25497819 25497930 G 1 11 48
chr8 25497869 25497980 H 1 12 49
按相同顺序排列的文件
如果可以安全地假设每个文件中的行的顺序相同,那么您可以使用以下方法非常简洁地完成此工作:
awk '
FILENAME != oname { FN++; oname = FILENAME }
{ p[FNR] = $1; s[FNR] = $2; e[FNR] = $3; n[FNR] = $4; f[FN,FNR] = $5; N = FNR }
END {
printf("%-8s %-12s %-12s %-4s %-5s %-5s %-5s\n",
"Part", "Start", "End", "Name", "File1", "File2", "File3");
for (i = 1; i <= N; i++)
{
printf("%-8s %-12d %-12d %-4s %-5d %-5d %-5d\n",
p[i], s[i], e[i], n[i], f[1,i], f[2,i], f[3,i]);
}
}' file_1.txt file_2.txt file_3.txt
不同顺序的文件
如果您不能依赖于每个文件中的记录顺序相同,那么您必须更加努力。假设第一个文件中的记录按所需顺序排列,则以下脚本将按顺序打印记录:
awk '
FILENAME != oname { FN++; oname = FILENAME }
{ key = $1 SUBSEP $2 SUBSEP $3 SUBSEP $4
if (FN == 1)
{ p[key] = $1; s[key] = $2; e[key] = $3; n[key] = $4; f[FN,key] = $5; k[FNR] = key; N = FNR }
else
{ if (key in p)
f[FN,key] = $5
else
printf "Unmatched key (%s) in %s\n", key, FILENAME
}
}
END {
printf("%-8s %-12s %-12s %-4s %-5s %-5s %-5s\n",
"Part", "Start", "End", "Name", "File1", "File2", "File3")
for (i = 1; i <= N; i++)
{
key = k[i]
printf("%-8s %-12d %-12d %-4s %-5d %-5d %-5d\n",
p[key], s[key], e[key], n[key], f[1,key], f[2,key], f[3,key])
}
}' "$@"
文件_5.txt
chr8 25497869 25497980 H 1
chr7 25497819 25497930 G 1
chr6 25497759 25497870 F 1
chr5 36259333 36259444 E 0
chr4 36259133 36259244 D 0
chr3 128205112 128205223 C 0
chr2 128205033 128205154 B 0
chr1 101845021 101845132 A 0
chr2 128205033 128205154 B 7
chr8 25497869 25497980 H 12
chr3 128205112 128205223 C 7
chr1 101845021 101845132 A 6
chr6 25497759 25497870 F 11
chr4 36259133 36259244 D 7
chr7 25497819 25497930 G 11
chr5 36259333 36259444 E 10
chr5 36259333 36259444 E 47
chr4 36259133 36259244 D 43
chr6 25497759 25497870 F 48
chr8 25497869 25497980 H 49
chr2 128205033 128205154 B 41
chr3 128205112 128205223 C 42
chr7 25497819 25497930 G 48
chr1 101845021 101845132 A 41
文件_6.txt
chr8 25497869 25497980 H 1
chr7 25497819 25497930 G 1
chr6 25497759 25497870 F 1
chr5 36259333 36259444 E 0
chr4 36259133 36259244 D 0
chr3 128205112 128205223 C 0
chr2 128205033 128205154 B 0
chr1 101845021 101845132 A 0
chr2 128205033 128205154 B 7
chr8 25497869 25497980 H 12
chr3 128205112 128205223 C 7
chr1 101845021 101845132 A 6
chr6 25497759 25497870 F 11
chr4 36259133 36259244 D 7
chr7 25497819 25497930 G 11
chr5 36259333 36259444 E 10
chr5 36259333 36259444 E 47
chr4 36259133 36259244 D 43
chr6 25497759 25497870 F 48
chr8 25497869 25497980 H 49
chr2 128205033 128205154 B 41
chr3 128205112 128205223 C 42
chr7 25497819 25497930 G 48
chr1 101845021 101845132 A 41
Part Start End Name File1 File2 File3
chr8 25497869 25497980 H 1 12 49
chr7 25497819 25497930 G 1 11 48
chr6 25497759 25497870 F 1 11 48
chr5 36259333 36259444 E 0 10 47
chr4 36259133 36259244 D 0 7 43
chr3 128205112 128205223 C 0 7 42
chr2 128205033 128205154 B 0 7 41
chr1 101845021 101845132 A 0 6 41
有许多情况下,这些脚本不能完全适应。例如,如果文件的长度不同;如果有重复按键;如果在一个或两个文件中找到密钥,而在其他文件中找不到密钥;如果第五列数据不是数字;如果第二列和第三列不是数字;如果仅列出两个文件,或列出三个以上的文件。“非数字”问题实际上很容易解决;只需使用%s
而不是%d
。但是脚本是脆弱的。它们在所示的生态系统中起作用,但不是很普遍。必要的修复并不是难以置信的困难;但是,它们必须编码,这是一个麻烦
可能有多于或少于3个文件
扩展上一个脚本以处理任意数量的文件,并输出制表符分隔的数据而不是格式化(可读)的数据并不困难
awk '
FILENAME != oname { FN++; file[FN] = oname = FILENAME }
{ key = $1 SUBSEP $2 SUBSEP $3 SUBSEP $4
if (FN == 1)
{ p[key] = $1; s[key] = $2; e[key] = $3; n[key] = $4; f[FN,key] = $5; k[FNR] = key; N = FNR }
else
{ if (key in p)
f[FN,key] = $5
else
{
printf "Unmatched key (%s) in %s\n", key, FILENAME
exit 1
}
}
}
END {
printf("%s\t%s\t%s\t%s", "Part", "Start", "End", "Name")
for (i = 1; i <= FN; i++) printf("\t%s", file[i]);
print ""
for (i = 1; i <= N; i++)
{
key = k[i]
printf("%s\t%s\t%s\t%s", p[key], s[key], e[key], n[key])
for (j = 1; j <= FN; j++)
printf("\t%s", f[j,key])
print ""
}
}' "$@"
按相同顺序排列的文件
如果可以安全地假设每个文件中的行的顺序相同,那么您可以使用以下方法非常简洁地完成此工作:
awk '
FILENAME != oname { FN++; oname = FILENAME }
{ p[FNR] = $1; s[FNR] = $2; e[FNR] = $3; n[FNR] = $4; f[FN,FNR] = $5; N = FNR }
END {
printf("%-8s %-12s %-12s %-4s %-5s %-5s %-5s\n",
"Part", "Start", "End", "Name", "File1", "File2", "File3");
for (i = 1; i <= N; i++)
{
printf("%-8s %-12d %-12d %-4s %-5d %-5d %-5d\n",
p[i], s[i], e[i], n[i], f[1,i], f[2,i], f[3,i]);
}
}' file_1.txt file_2.txt file_3.txt
不同顺序的文件
如果您不能依赖于每个文件中的记录顺序相同,那么您必须更加努力。假设第一个文件中的记录按所需顺序排列,则以下脚本将按顺序打印记录:
awk '
FILENAME != oname { FN++; oname = FILENAME }
{ key = $1 SUBSEP $2 SUBSEP $3 SUBSEP $4
if (FN == 1)
{ p[key] = $1; s[key] = $2; e[key] = $3; n[key] = $4; f[FN,key] = $5; k[FNR] = key; N = FNR }
else
{ if (key in p)
f[FN,key] = $5
else
printf "Unmatched key (%s) in %s\n", key, FILENAME
}
}
END {
printf("%-8s %-12s %-12s %-4s %-5s %-5s %-5s\n",
"Part", "Start", "End", "Name", "File1", "File2", "File3")
for (i = 1; i <= N; i++)
{
key = k[i]
printf("%-8s %-12d %-12d %-4s %-5d %-5d %-5d\n",
p[key], s[key], e[key], n[key], f[1,key], f[2,key], f[3,key])
}
}' "$@"
文件_5.txt
chr8 25497869 25497980 H 1
chr7 25497819 25497930 G 1
chr6 25497759 25497870 F 1
chr5 36259333 36259444 E 0
chr4 36259133 36259244 D 0
chr3 128205112 128205223 C 0
chr2 128205033 128205154 B 0
chr1 101845021 101845132 A 0
chr2 128205033 128205154 B 7
chr8 25497869 25497980 H 12
chr3 128205112 128205223 C 7
chr1 101845021 101845132 A 6
chr6 25497759 25497870 F 11
chr4 36259133 36259244 D 7
chr7 25497819 25497930 G 11
chr5 36259333 36259444 E 10
chr5 36259333 36259444 E 47
chr4 36259133 36259244 D 43
chr6 25497759 25497870 F 48
chr8 25497869 25497980 H 49
chr2 128205033 128205154 B 41
chr3 128205112 128205223 C 42
chr7 25497819 25497930 G 48
chr1 101845021 101845132 A 41
文件_6.txt
chr8 25497869 25497980 H 1
chr7 25497819 25497930 G 1
chr6 25497759 25497870 F 1
chr5 36259333 36259444 E 0
chr4 36259133 36259244 D 0
chr3 128205112 128205223 C 0
chr2 128205033 128205154 B 0
chr1 101845021 101845132 A 0
chr2 128205033 128205154 B 7
chr8 25497869 25497980 H 12
chr3 128205112 128205223 C 7
chr1 101845021 101845132 A 6
chr6 25497759 25497870 F 11
chr4 36259133 36259244 D 7
chr7 25497819 25497930 G 11
chr5 36259333 36259444 E 10
chr5 36259333 36259444 E 47
chr4 36259133 36259244 D 43
chr6 25497759 25497870 F 48
chr8 25497869 25497980 H 49
chr2 128205033 128205154 B 41
chr3 128205112 128205223 C 42
chr7 25497819 25497930 G 48
chr1 101845021 101845132 A 41
Part Start End Name File1 File2 File3
chr8 25497869 25497980 H 1 12 49
chr7 25497819 25497930 G 1 11 48
chr6 25497759 25497870 F 1 11 48
chr5 36259333 36259444 E 0 10 47
chr4 36259133 36259244 D 0 7 43
chr3 128205112 128205223 C 0 7 42
chr2 128205033 128205154 B 0 7 41
chr1 101845021 101845132 A 0 6 41
有许多情况下,这些脚本不能完全适应。例如,如果文件的长度不同;如果有重复按键;如果在一个或两个文件中找到密钥,而在其他文件中找不到密钥;如果第五列数据不是数字;如果第二列和第三列不是数字;如果仅列出两个文件,或列出三个以上的文件。“非数字”问题实际上很容易解决;只需使用%s
而不是%d
。但是脚本是脆弱的。它们在所示的生态系统中起作用,但不是很普遍。必要的修复并不是难以置信的困难;但是,它们必须编码,这是一个麻烦
可能有多于或少于3个文件
扩展上一个脚本以处理任意数量的文件,并输出制表符分隔的数据而不是格式化(可读)的数据并不困难
awk '
FILENAME != oname { FN++; file[FN] = oname = FILENAME }
{ key = $1 SUBSEP $2 SUBSEP $3 SUBSEP $4
if (FN == 1)
{ p[key] = $1; s[key] = $2; e[key] = $3; n[key] = $4; f[FN,key] = $5; k[FNR] = key; N = FNR }
else
{ if (key in p)
f[FN,key] = $5
else
{
printf "Unmatched key (%s) in %s\n", key, FILENAME
exit 1
}
}
}
END {
printf("%s\t%s\t%s\t%s", "Part", "Start", "End", "Name")
for (i = 1; i <= FN; i++) printf("\t%s", file[i]);
print ""
for (i = 1; i <= N; i++)
{
key = k[i]
printf("%s\t%s\t%s\t%s", p[key], s[key], e[key], n[key])
for (j = 1; j <= FN; j++)
printf("\t%s", f[j,key])
print ""
}
}' "$@"
假设这三个文件都已排序,则可以使用
join
命令:
join -o "1.1,1.2,1.3,1.4,2.5,2.6,1.5" file3 <(join -o "1.1,1.2,1.3,1.4,1.5,2.5" file1 file2)
假设这三个文件都已排序,则可以使用
join
命令:
join -o "1.1,1.2,1.3,1.4,2.5,2.6,1.5" file3 <(join -o "1.1,1.2,1.3,1.4,1.5,2.5" file1 file2)
嗨,约翰,我不知道该怎么办?因为我只想从每个文件中添加第5列作为最终文件中的新列。是的,所有文件都有相同的读取记录。另外,我想给这些列添加标题,因为我知道我的文件需要什么标题。嗨,John,我不知道该怎么做?因为我只想从每个文件中添加第5列作为最终文件中的新列。是的,所有文件都有相同的读取记录。此外,我还想为这些列添加标题,因为我知道我要为我的文件添加什么标题。我可能应该补充一点,我怀疑我忽略了一个简单的解决方案,尽管再次强调,这取决于代码在面对数据文件中的不规则时需要有多大的弹性。嗨,Jon,感谢您的输入,但是,此代码不发送创建制表符分隔的文件输出。如果我有三个以上的文件呢。每次文件的数量都会有所不同。是否有一个统一的awk代码可供使用,而不考虑我拥有的文件数量?因此,将格式更改为在字段之间使用制表符(
\t
);也删除字段大小。这种改变很容易。我给出了格式良好的输出。如果你想要标签,那很好,但是它们不能很好地呈现在屏幕上。原则上,在将OFS设置为“\t”
后,可以将printf
调用替换为print
调用。文件数量的变化主要是安排在循环中打印尾随字段的问题,而不是像代码中那样硬编码3。再次,直截了当地处理。但是,由于print
以换行符结束其输出,因此您必须返回到printf
,我无法循环它。抱歉,我是新手。@RonicK:请参阅我答案底部的“更新”部分。我可能应该补充一点,我怀疑我忽略了一个简单的解决方案,不过,这取决于代码在面对数据文件中的不规则时需要有多大的弹性。嗨,Jon,谢谢你的输入,但是,此代码不发送创建制表符分隔的文件输出。如果我有三个以上的文件呢。每次文件的数量都会有所不同。是否有一个统一的awk代码可供使用,而不考虑我拥有的文件数量?因此,将格式更改为在字段之间使用制表符(\t
);也删除字段大小。这种改变很容易。我给出了格式良好的输出。如果你想要标签,那很好,但是它们不能很好地呈现在屏幕上。原则上,在将OFS设置为“\t”
后,可以将printf
调用替换为print
调用。变数