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

我是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_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 number
4
映射到
继承的
而不是您在预期输出中的父系

假设您真的不需要出于某些其他原因将数字和名称列表定义为两个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显式编码,但我们假设这个数字可能会改变;我们将