AWK:使用第一行的信息在每一行前面加上
AWK: Use First Line's Info to prepend each line
我在 bash 脚本中有一个 awk 1 衬里。
在做 awk 行时需要帮助...
这是我尝试过的方法,但没有用。
这是我的 data.vcf
. abc hji ran kls
CHR1 0/0 0/0 0/1 0/0
CHR2 0/1 0/0 0/0 0/0
CHR3 1/1 0/0 0/0 0/0
CHR4 0/0 0/0 0/0 1/1
我目前的代码(其他 bash 代码不相关):
awk '{ for (i=1; i<=NF; ++i) { if ($i ~ "/1") print NR==1 $i," ",[=11=]} }' data.vcf
这会打印:
. abc hji ran kls
0 CHR1 0/0 0/0 0/1 0/0
0 CHR2 0/1 0/0 0/0 0/0
0 CHR3 1/1 0/0 0/0 0/0
0 CHR4 0/0 0/0 0/0 1/1
我希望它打印这个:
. abc hji ran kls
ran CHR1 0/0 0/0 0/1 0/0
abc CHR2 0/1 0/0 0/0 0/0
abc CHR3 1/1 0/0 0/0 0/0
kls CHR4 0/0 0/0 0/0 1/1
基本上,只需在 awk 命令的 $i 前面加上 space,但仅在第一行使用 $i。谢谢你的帮助。
以下 tesprog.awk
脚本将为您提供所需内容:
NR==1 {
for (i = 2; i <= NF; i++) {
txt[i] = $i;
}
print [=10=];
}
NR > 1 {
pos = 0;
for (i = 2; i <= NF; i++) {
if ($i != "0/0") {
pos = i;
}
}
print txt[pos]" "[=10=];
}
它使用第一条记录创建一个包含 header 列的数组,然后,对于所有其他记录,它查找 不是 0/0
并存储位置。
然后它使用该位置查找文本以作为该行的前缀。
您给定的测试数据的输出是:
pax> awk -f testprog.awk testprog.in
. abc hji ran kls
ran CHR1 0/0 0/0 0/1 0/0
abc CHR2 0/1 0/0 0/0 0/0
abc CHR3 1/1 0/0 0/0 0/0
kls CHR4 0/0 0/0 0/0 1/1
现在,可能需要进行一些调整,如果我没有完全正确地选择标准,if ($i != "0/0")
,但这应该是一个相当小的调整改变。如果有多个可能的匹配项,它还会选择 last 匹配列,因此,如果可能的话,您应该指定在这种情况下所需的行为。
要在 bash
脚本中执行此操作而不需要单独的 awk
脚本,只需使用:
awk '
NR==1 {
for (i = 2; i <= NF; i++) {
txt[i] = $i;
}
print [=12=];
}
NR > 1 {
pos = 0;
for (i = 2; i <= NF; i++) {
if ($i != "0/0") {
pos = i;
}
}
print txt[pos]" "[=12=];
}' testprog.in
或者,如果您真的想要 one-liner,它将是 long-ish 行,而不是 相当 与完全展开的变体一样可读:
awk 'NR==1{for(i=2;i<=NF;i++){t[i]=$i}print [=13=]}NR>1{p=0;for(i=2;i<=NF;i++){if($i!="0/0"){p=i}}print t[p]" "[=13=]}' testprog.in
这是另一种变体:
awk 'NR==1 {for (i=2;i<=NF;i++) a[i]=$i;print;next} {for (i=2;i<=NF;i++) if ($i~"/1") =a[i]FS}1' file
. abc hji ran kls
ran CHR1 0/0 0/0 0/1 0/0
abc CHR2 0/1 0/0 0/0 0/0
abc CHR3 1/1 0/0 0/0 0/0
kls CHR4 0/0 0/0 0/0 1/1
工作原理:
awk '
NR==1 { # For line "1"
for (i=2;i<=NF;i++) # Loop trough all elements
a[i]=$i # Store them in an array "a" using field location as reference
print # Print the line
next} # Do nothing more with line "1"
{for (i=2;i<=NF;i++) # Loop trough all fields of all other line
if ($i~"/1") # If field location contains "/1"
=a[i]FS} # Use that field number and get information from first line
1 # Print all out
' file # Read the file
我在 bash 脚本中有一个 awk 1 衬里。 在做 awk 行时需要帮助... 这是我尝试过的方法,但没有用。
这是我的 data.vcf
. abc hji ran kls
CHR1 0/0 0/0 0/1 0/0
CHR2 0/1 0/0 0/0 0/0
CHR3 1/1 0/0 0/0 0/0
CHR4 0/0 0/0 0/0 1/1
我目前的代码(其他 bash 代码不相关):
awk '{ for (i=1; i<=NF; ++i) { if ($i ~ "/1") print NR==1 $i," ",[=11=]} }' data.vcf
这会打印:
. abc hji ran kls
0 CHR1 0/0 0/0 0/1 0/0
0 CHR2 0/1 0/0 0/0 0/0
0 CHR3 1/1 0/0 0/0 0/0
0 CHR4 0/0 0/0 0/0 1/1
我希望它打印这个:
. abc hji ran kls
ran CHR1 0/0 0/0 0/1 0/0
abc CHR2 0/1 0/0 0/0 0/0
abc CHR3 1/1 0/0 0/0 0/0
kls CHR4 0/0 0/0 0/0 1/1
基本上,只需在 awk 命令的 $i 前面加上 space,但仅在第一行使用 $i。谢谢你的帮助。
以下 tesprog.awk
脚本将为您提供所需内容:
NR==1 {
for (i = 2; i <= NF; i++) {
txt[i] = $i;
}
print [=10=];
}
NR > 1 {
pos = 0;
for (i = 2; i <= NF; i++) {
if ($i != "0/0") {
pos = i;
}
}
print txt[pos]" "[=10=];
}
它使用第一条记录创建一个包含 header 列的数组,然后,对于所有其他记录,它查找 不是 0/0
并存储位置。
然后它使用该位置查找文本以作为该行的前缀。
您给定的测试数据的输出是:
pax> awk -f testprog.awk testprog.in
. abc hji ran kls
ran CHR1 0/0 0/0 0/1 0/0
abc CHR2 0/1 0/0 0/0 0/0
abc CHR3 1/1 0/0 0/0 0/0
kls CHR4 0/0 0/0 0/0 1/1
现在,可能需要进行一些调整,如果我没有完全正确地选择标准,if ($i != "0/0")
,但这应该是一个相当小的调整改变。如果有多个可能的匹配项,它还会选择 last 匹配列,因此,如果可能的话,您应该指定在这种情况下所需的行为。
要在 bash
脚本中执行此操作而不需要单独的 awk
脚本,只需使用:
awk '
NR==1 {
for (i = 2; i <= NF; i++) {
txt[i] = $i;
}
print [=12=];
}
NR > 1 {
pos = 0;
for (i = 2; i <= NF; i++) {
if ($i != "0/0") {
pos = i;
}
}
print txt[pos]" "[=12=];
}' testprog.in
或者,如果您真的想要 one-liner,它将是 long-ish 行,而不是 相当 与完全展开的变体一样可读:
awk 'NR==1{for(i=2;i<=NF;i++){t[i]=$i}print [=13=]}NR>1{p=0;for(i=2;i<=NF;i++){if($i!="0/0"){p=i}}print t[p]" "[=13=]}' testprog.in
这是另一种变体:
awk 'NR==1 {for (i=2;i<=NF;i++) a[i]=$i;print;next} {for (i=2;i<=NF;i++) if ($i~"/1") =a[i]FS}1' file
. abc hji ran kls
ran CHR1 0/0 0/0 0/1 0/0
abc CHR2 0/1 0/0 0/0 0/0
abc CHR3 1/1 0/0 0/0 0/0
kls CHR4 0/0 0/0 0/0 1/1
工作原理:
awk '
NR==1 { # For line "1"
for (i=2;i<=NF;i++) # Loop trough all elements
a[i]=$i # Store them in an array "a" using field location as reference
print # Print the line
next} # Do nothing more with line "1"
{for (i=2;i<=NF;i++) # Loop trough all fields of all other line
if ($i~"/1") # If field location contains "/1"
=a[i]FS} # Use that field number and get information from first line
1 # Print all out
' file # Read the file