Bash 在awk中用各自的字符串替换数字
我是bash/awk编程的新手,我有一个如下文件:Bash 在awk中用各自的字符串替换数字,bash,awk,Bash,Awk,我是bash/awk编程的新手,我有一个如下文件: 1 10032154 10032154 A C Leber_congenital_amaurosis_9 criteria_provided,_single_submitter Benign . 1 1 10032184 10032184 A G Retinal_dystrophy|Leber_congenital_amaurosis_9|not_provided criteria_p
1 10032154 10032154 A C Leber_congenital_amaurosis_9 criteria_provided,_single_submitter Benign . 1
1 10032184 10032184 A G Retinal_dystrophy|Leber_congenital_amaurosis_9|not_provided criteria_provided,_multiple_submitters,_no_conflicts Pathogenic/Likely_pathogenic . 1,4
1 10032209 10032209 G A not_provided criteria_provided,_single_submitter Likely_benign . 8,64,512
1 10032154 10032154 A C Leber_congenital_amaurosis_9 criteria_provided,_single_submitter Benign . germline
1 10032184 10032184 A G Retinal_dystrophy|Leber_congenital_amaurosis_9|not_provided criteria_provided,_multiple_submitters,_no_conflicts Pathogenic/Likely_pathogenic . germline,paternal
1 10032209 10032209 G A not_provided criteria_provided,_single_submitter Likely_benign . paternal,biparental,tested-inconclusive
使用awk,我想更改最后一列中的数字($10)及其说明。我在两个不同的数组中分配了数字及其定义。我当时的想法是通过将两个数组迭代在一起来更改这些数字。这里,0表示“未知”,1表示“生殖系”,4表示“体细胞”,并继续
z=(0 1 2 4 8 16 32 64 128 256 512 1024 1073741824)
t=("unknown" "germline" "somatic" "inherited" "paternal" "maternal" "de-novo" "biparental" "uniparental" "not-tested" "tested-inconclusive" "not-reported" "other")
number=$(IFS=,; echo "${z[*]}")
def=$(IFS=,; echo "${t[*]}")
awk -v a="$number" -v b="${def}" 'BEGIN { OFS="\t" } /#/ {next}
{
x=split(a, e, /,/)
y=split(b, f, /,/)
delete c
m=split($10, c, /,/)
for (i=1; i<=m; i++) {
for (j=1; j<=x; j++) {
if (c[i]==e[j]) {
c[i]=f[j]
}
}
$10+=sprintf("%s, ",c[i])
}
print $1, $2, $3, $4, $5, $6, $7, $8, $9, $10
}' input.vcf > output.vcf
如果你能帮助我,我将非常高兴
所有最好的都使用以下简短的Perl内嵌脚本:
perl -F'\t' -lane '
BEGIN {
@keys = qw( 0 1 2 4 8 16 32 64 128 256 512 1024 1073741824 );
@vals = qw( unknown germline somatic inherited paternal maternal de-novo biparental uniparental not-tested tested-inconclusive not-reported other );
%val = map { $keys[$_] => $vals[$_] } 0..$#keys;
}
print join "\t", @F[0..8], ( join ",", map { $val{$_} } split /,/, $F[9] );
' in_file > out_file
Perl脚本使用以下命令行标志:-e
:告诉Perl在线查找代码,而不是在文件中。-n
:一次循环输入一行,默认情况下将其分配给$。
-l
:在行内执行代码之前,先去掉输入行分隔符(“\n”
,默认情况下在*NIX上),然后在打印时将其追加。
-a
:在空格或-F
选项中指定的正则表达式上将$\ucode>拆分为数组@F
。
-F'/\t/'
:在选项卡上拆分为@F
,而不是在空白处
%val=map{$keys[$\u]=>$vals[$\u]}0..$\keys代码>:创建%val
-一个哈希查找表,其中键=数字代码,值=变异/变体类型
注意,在Perl中,数组是0索引的
另请参见:
使用以下简短的Perl内嵌脚本:
perl -F'\t' -lane '
BEGIN {
@keys = qw( 0 1 2 4 8 16 32 64 128 256 512 1024 1073741824 );
@vals = qw( unknown germline somatic inherited paternal maternal de-novo biparental uniparental not-tested tested-inconclusive not-reported other );
%val = map { $keys[$_] => $vals[$_] } 0..$#keys;
}
print join "\t", @F[0..8], ( join ",", map { $val{$_} } split /,/, $F[9] );
' in_file > out_file
Perl脚本使用以下命令行标志:
-e
:告诉Perl在线查找代码,而不是在文件中。
-n
:一次循环输入一行,默认情况下将其分配给$。
-l
:在行内执行代码之前,先去掉输入行分隔符(“\n”
,默认情况下在*NIX上),然后在打印时将其追加。
-a
:在空格或-F
选项中指定的正则表达式上将$\ucode>拆分为数组@F
。
-F'/\t/'
:在选项卡上拆分为@F
,而不是在空白处
%val=map{$keys[$\u]=>$vals[$\u]}0..$\keys代码>:创建%val
-一个哈希查找表,其中键=数字代码,值=变异/变体类型
注意,在Perl中,数组是0索引的
另请参见:
您可以使用此awk
:
z=(01 2 4 8 16 32 64 128 256 512 1024 1073741824)
t=(“未知”“种系”“体”“遗传”“父系”“母系”“从头”“双亲”“单亲”“未检测”“检测不确定”“未报告”“其他”)
awk-v z=“${z[*]}”-v t=“${t[*]}”
开始{
分裂(z,zarr)
分离(t,tarr)
对于(i=1;i在zarr中;++i)
map[zarr[i]]=tarr[i]
}
{
拆分($NF,arr,/,/)
s=“”
对于(i=1;阵列中的i;++i)
s=s(i=1?“:”,“)映射[arr[i]]
$NF=s;
}
1.
"档案"
btw编号4
被映射到继承的而不是父系的。您可以使用此awk
:
z=(01 2 4 8 16 32 64 128 256 512 1024 1073741824)
t=(“未知”“种系”“体”“遗传”“父系”“母系”“从头”“双亲”“单亲”“未检测”“检测不确定”“未报告”“其他”)
awk-v z=“${z[*]}”-v t=“${t[*]}”
开始{
分裂(z,zarr)
分离(t,tarr)
对于(i=1;i在zarr中;++i)
map[zarr[i]]=tarr[i]
}
{
拆分($NF,arr,/,/)
s=“”
对于(i=1;阵列中的i;++i)
s=s(i=1?“:”,“)映射[arr[i]]
$NF=s;
}
1.
"档案"
btw number4
映射到继承的
而不是您在预期输出中的父系
。假设您真的不需要出于某些其他原因将数字和名称列表定义为两个shell数组:
$ cat tst.awk
BEGIN {
split("0 1 2 4 8 16 32 64 128 256 512 1024 1073741824",nrsArr)
split("unknown germline somatic inherited paternal maternal de-novo biparental uniparental not-tested tested-inconclusive not-reported other",namesArr)
for (i in nrsArr) {
nr2name[nrsArr[i]] = namesArr[i]
}
}
!/#/ {
n = split($NF,nrs,/,/)
sub(/[^[:space:]]+$/,"")
printf "%s", $0
for (i=1; i<=n; i++) {
printf "%s%s", nr2name[nrs[i]], (i<n ? "," : ORS)
}
}
以上内容保留了输入文件中的所有空白,以备不时之需。假设您不需要出于其他原因将数字和名称列表定义为两个shell数组:
$ cat tst.awk
BEGIN {
split("0 1 2 4 8 16 32 64 128 256 512 1024 1073741824",nrsArr)
split("unknown germline somatic inherited paternal maternal de-novo biparental uniparental not-tested tested-inconclusive not-reported other",namesArr)
for (i in nrsArr) {
nr2name[nrsArr[i]] = namesArr[i]
}
}
!/#/ {
n = split($NF,nrs,/,/)
sub(/[^[:space:]]+$/,"")
printf "%s", $0
for (i=1; i<=n; i++) {
printf "%s%s", nr2name[nrs[i]], (i<n ? "," : ORS)
}
}
上述内容保留了输入文件中的所有空白,以防出现问题。假设:
- OP事先已确认
z
和t
数组有效(例如,两个数组中的元素数相同)
- OP可能希望(动态)更改
z
和t
数组的内容,因此我们将把数组分配留在bash
级别(即,不会在awk
中硬编码)
- 替换字符串可能包含空格,因此我们将保留OP当前构建逗号分隔字符串的方法(从
z
和t
)数组;还假设替换字符串不包含逗号;这将简化awk
- 虽然OP已经为(
awk
)字段#10显式编码,但我们假设这个数字可能会改变;我们将重点处理一行中的最后一个字段
初始化代码的小更改:
# original arrays
z=(0 1 2 4 8 16 32 64 128 256 512 1024 1073741824)
t=("unknown" "germline" "somatic" "inherited" "paternal" "maternal" "de-novo" "biparental" "uniparental" "not-tested" "tested-inconclusive" "not-reported" "other")
# renamed variables (format: x,y,z,...)
nums=$(IFS=,; echo "${z[*]}")
alphas=$(IFS=,; echo "${t[*]}")
一个awk
idea:
awk -v nums="${nums}" -v alphas="${alphas}" ' # pass comma-delimited variables to awk
BEGIN { OFS="\t" # copied from original code:w
n=split(nums,num,/,/) # split comma-delimted variables
a=split(alphas,alpha,/,/) # into arrays
}
/#/ { next } # copied from original code
{ l=split($NF,lastf,/,/) # split the last (comma-delimited) field
$NF="" # clear the last field
pfx="" # initialize our prefix string
for (i=1; i<=l; i++) # loop through entries in the last field
for (j=1; j<=n; j++) # loop through array of numbers
if ( lastf[i] == num[j] ) # if array entries match ...
{ $NF= $NF pfx alpha[j] # append the associated alpha to the last field
pfx="," # set the prefix to "," for the next item
break # break out one level to process next entry in the last field
}
}
{ print } # print the current line (with modified last field)
' input.vcf
假设:
- OP事先已确认
z
和t
数组有效(例如,两个数组中的元素数相同)
- OP可能希望(动态)更改
z
和t
数组的内容,因此我们将把数组分配留在bash
级别(即,不会在awk
中硬编码)
- 替换字符串可能包含空格,因此我们将保留OP当前构建逗号分隔字符串的方法(从
z
和t
)数组;还假设替换字符串不包含逗号;这将简化awk
- 虽然OP已经为(
awk
)字段#10显式编码,但我们假设这个数字可能会改变;我们将