Bash 要匹配,请在修改列输入并向输出文件添加额外列的同时合并两个文件
我想合并2个文件并将其分配给一个新文件,同时在unix中使用awk添加一个新的不存在的列: 文件1:VDR.txt没有标题,以空格分隔,如下所示:Bash 要匹配,请在修改列输入并向输出文件添加额外列的同时合并两个文件,bash,unix,awk,merge,Bash,Unix,Awk,Merge,我想合并2个文件并将其分配给一个新文件,同时在unix中使用awk添加一个新的不存在的列: 文件1:VDR.txt没有标题,以空格分隔,如下所示: chr12-45000000-50000000 --- rs192072617 48225416 0.000 0.270 0.999 0 -1 -1 -1 chr12-45000000-50000000 --- rs181728325 48225429 0.000 0.144 1.000 0 -1 -1 -1 chr12-45000000-50000
chr12-45000000-50000000 --- rs192072617 48225416 0.000 0.270 0.999 0 -1 -1 -1
chr12-45000000-50000000 --- rs181728325 48225429 0.000 0.144 1.000 0 -1 -1 -1
chr12-45000000-50000000 --- rs187216594 48225500 0.000 0.007 1.000 0 -1 -1 -1
MarkerName Allele1 Allele2 Weight Zscore P-value Direction HetISq HetChiSq HetDf HetPVal
rs192072617 a g 2887.00 1.579 0.1143 ++ 0.0 0.032 1 0.8579
rs7929618 c g 2887.00 -1.416 0.1568 -+ 47.4 1.899 1 0.1681
rs181728325 t c 2887.00 1.469 0.1419 ++ 73.9 3.830 1 0.05033
rs7190157 a c 2887.00 1.952 0.05088 +- 72.7 3.669 1 0.05542
rs12364336 a g 2887.00 -1.503 0.1328 -+ 69.8 3.306 1 0.06902
rs187216594 t c 2887.00 -0.082 0.9349 +- 74.8 3.964 1 0.04649
rs12562373 a g 2887.00 -0.290 0.7717 -+ 0.0 0.150 1 0.6984
文件2:METAL1.tbl有一个标题,由制表符分隔,如下所示:
chr12-45000000-50000000 --- rs192072617 48225416 0.000 0.270 0.999 0 -1 -1 -1
chr12-45000000-50000000 --- rs181728325 48225429 0.000 0.144 1.000 0 -1 -1 -1
chr12-45000000-50000000 --- rs187216594 48225500 0.000 0.007 1.000 0 -1 -1 -1
MarkerName Allele1 Allele2 Weight Zscore P-value Direction HetISq HetChiSq HetDf HetPVal
rs192072617 a g 2887.00 1.579 0.1143 ++ 0.0 0.032 1 0.8579
rs7929618 c g 2887.00 -1.416 0.1568 -+ 47.4 1.899 1 0.1681
rs181728325 t c 2887.00 1.469 0.1419 ++ 73.9 3.830 1 0.05033
rs7190157 a c 2887.00 1.952 0.05088 +- 72.7 3.669 1 0.05542
rs12364336 a g 2887.00 -1.503 0.1328 -+ 69.8 3.306 1 0.06902
rs187216594 t c 2887.00 -0.082 0.9349 +- 74.8 3.964 1 0.04649
rs12562373 a g 2887.00 -0.290 0.7717 -+ 0.0 0.150 1 0.6984
文件的行数不等,第一个文件(VDR.txt)比第二个文件(METAL1.tbl)短得多
我想:
gene MarkerName chr BP impute Allele1 Allele2 Weight Zscore P-value Direction HetISq HetChiSq HetDf HetPVal
VDR rs192072617 chr12 48225416 --- a g 2887 1.579 0.1143 ++ 0 0.032 1 0.8579
VDR rs181728325 chr12 48225429 --- t c 2887 1.469 0.1419 ++ 73.9 3.83 1 0.05033
VDR rs187216594 chr12 48225500 --- t c 2887 -0.082 0.9349 +- 74.8 3.964 1 0.04649
我的尝试是:
$ awk 'FNR==NR {a[$1]=$1" "$2" "$3" "$4" "$5;next}{print $3, gensub(/-.*/, "", $1), $4, $2, a[$3]}' METAL1.tbl VDR.txt
它确实以正确的方式获取了chr列和列顺序,但不幸的是,它只打印VDR.txt中需要的列,而没有打印合并文件
我知道这是一个相当复杂的例子,任何帮助或建议都将不胜感激
谢谢,Mel我已经对两个数据文件进行了排序,以使用
join
命令-这会影响输出中的行顺序-如果不需要,我可以使用另一种方法
export LANG=C
genef=$1
metalf=$2
gene=$(basename $genef .txt)
join -13 -21 <(sort -k3,3 $genef) <(sort -k1,1 $metalf)|
awk -vgene=$gene '
{
marker=$1
chr=substr($2, 1, index($2, "-")-1)
bp=$4
impute=$3
printf("%s\t%s\t%s\t%s\t%s", gene, marker, chr, bp, impute)
for(i=12; i<=NF; ++i)
printf("\t%s", $i)
printf("\n")
}
'
只要不需要标题行,它就可以直接用一个相当简单的
awk
脚本:
$ awk 'FNR == NR { sub(/-.*/, "", $1); row[$3] = "VDR " $3 " " $1 " " $4 " " $2 }
> FNR != NR { if ($1 in row) { name = $1; $1 = ""; print row[name] $0 } }' \
> VDR.txt METAL1.tbl
VDR rs192072617 chr12 48225416 --- a g 2887.00 1.579 0.1143 ++ 0.0 0.032 1 0.8579
VDR rs181728325 chr12 48225429 --- t c 2887.00 1.469 0.1419 ++ 73.9 3.830 1 0.05033
VDR rs187216594 chr12 48225500 --- t c 2887.00 -0.082 0.9349 +- 74.8 3.964 1 0.04649
$
文件必须按显示的顺序列出才能正常工作
FNR==NR
行处理第一个文件。sub
在第一个字段中删除第一个破折号及其后的所有内容;分配由$3
中的标记名键入,并包含行开始的信息-固定代码、标记名、减少的染色体数、BP和标记为“插补”的破折号集
FNR!=NR
line处理其他文件。当列1中的值与行
数组中的一个键匹配时,从当前行中删除该键(在$0
开头保留一个空白),然后打印与$0
连接的行
中的值
无需对航向线进行特殊处理;值MarkerName
与第一个文件中的任何实际标记名都不匹配,因此该行将被忽略
$ cat > test.awk
NR==FNR {
sub(/-.*/,"",$1) # remove from 1st dash forward
a[$3]="VDR" OFS $3 OFS $1 OFS $4 OFS $2 # cols 1-4 of the 1st file
next
}
FNR==1 {
printf "%s", "H0" OFS "H3" OFS "H1" OFS "H4" OFS "H2" # 1st part of header
}
FNR==1 || $1 in a { # header and matching rows
print a[$1], $0 # print'em
}
$ awk -f test.awk VDR.txt METAL1.tbl
H0 H3 H1 H4 H2 MarkerName Allele1 Allele2 Weight Zscore P-value Direction HetISq HetChiSq HetDf HetPVal
VDR rs192072617 chr12 48225416 --- rs192072617 a g2887.00 1.579 0.1143 ++ 0.0 0.032 1 0.8579
VDR rs181728325 chr12 48225429 --- rs181728325 t c2887.00 1.469 0.1419 ++ 73.9 3.830 1 0.05033
VDR rs187216594 chr12 48225500 --- rs187216594 t c2887.00 -0.082 0.9349 +- 74.8 3.964 1 0.04649
作为一个班轮:
awk 'NR==FNR { sub(/-.*/,"",$1); a[$3]="VDR" OFS $3 OFS $1 OFS $4 OFS $2; next} FNR==1 {printf "%s", "H0" OFS "H3" OFS "H1" OFS "H4" OFS "H2"} FNR==1 || $1 in a {print a[$1], $0}' VDR.txt METAL1.tbl
你有没有试图解决这个问题?如果是这样,你应该分享这个。以“这是我的规格,请为我编码”的形式提出的问题通常不受欢迎,但以“这是我的代码,这是我遇到问题的部分”的形式提出的问题是。文件中的字段是如何识别的?固定宽度?或者分隔符是什么?我建议将数据样本减少到4列左右(刚好足以解决根本问题)。您是否知道unix/linux命令
join
?如果您可以使用分隔数据(如|
或tab),您可能可以在一行中完成您想要的操作。但是我没有仔细查看您的输入和输出(因为它们太宽;-),所以我可能是错的。祝你好运。你真的需要简化或澄清你的项目符号(3)只保留第一个文件(VDR.txt)第一列中第一个破折号之前的字符——在第一个破折号之前,而不是在前4个破折号之前,以避免染色体数小于10的破折号(例如,不希望有chr7,但要有chr7)。您的示例数据没有chr7
引用,因此不清楚这是怎么回事。从chr12-45000000-50000000
类型名称中获取chr12
很容易理解,但是您只是想从chr7-45000000-50000000
中获取chr7
?“你既没有演示也没有解释这个额外的皱纹。”乔纳坦利弗勒我简化了子弹3。很抱歉造成混淆,我想写一个多功能的函数,可以用于其他可能有一些差异的文件。(但不幸的是,我有点懒得给出正确的例子)--也非常感谢您提供的解决方案,效果很好,速度也很快!并添加BEGIN{print“header you want”}
非常感谢您的帮助,这非常有效,但我正在寻找类似Jonathan Leffler的解决方案的一行程序。感谢您的建议,但我不喜欢join
的原因是我必须订购文件。。。对于第一个文件(VDR.txt),这将是一项简单的任务,但对于第二个文件(METAL1.tbl),这是一个相当大的文件(约600 Mb)。排序METAL1.tbl只是不断给我错误,增加了更多的处理时间,这就是为什么我一直在寻找一个解决方案围绕awk。好的点-排序600MB是相当快的-但一个单一的通过awk总是好的-你看到什么错误与排序?