String awk子检查元素并将条目添加到列表中

String awk子检查元素并将条目添加到列表中,string,awk,substring,substitution,String,Awk,Substring,Substitution,我有一个字符串: 1 9790725 . TTCCTCC T。ACMG=美国;良性_cv=0;ccds_转录本=真;克林根=0 1 9790725 . TTCCTCC T。ACMG=美国;良性_cv=0;已接受=入口0,入口1;ccds_转录本=真;克林根=1 我需要检查接受的元素是否=entry0,entry1,…,entryN;已在最后一列中。如果: 如示例的第2行所示:在逗号分隔的值列表中添加一个元素,例如entryX。e、 g.获得接受=entry0,entry1,ent

我有一个字符串:

1 9790725 . TTCCTCC T。ACMG=美国;良性_cv=0;ccds_转录本=真;克林根=0 1 9790725 . TTCCTCC T。ACMG=美国;良性_cv=0;已接受=入口0,入口1;ccds_转录本=真;克林根=1 我需要检查接受的元素是否=entry0,entry1,…,entryN;已在最后一列中。如果:

如示例的第2行所示:在逗号分隔的值列表中添加一个元素,例如entryX。e、 g.获得接受=entry0,entry1,entryX;from accepted=entry0,entry1;在示例的第2行中 如示例的第1行中所示,不存在。将其添加为accepted=entryX;。 注意:也可以是单个元素,例如accepted=entry0;没有逗号

我试过这个命令:

awk-F'\t'$2==9790725{if$0~/\;accepted=/{sub/accepted=[^;]*/,accepted=entryX}其他{sub/accepted=.*?$/,accepted=entryX;}}1'文件 但我只能替换它的值,或者在不存在的情况下创建它,而不能附加到条目列表中

如何使用awk命令子系统执行此操作


提前非常感谢您的帮助

字符串函数文档:

与sub:

如果替换中出现特殊字符“&”,则表示由regexp匹配的精确子字符串

结果:

1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;ccds_transcript=true;clingen=0;accepted=entryX;
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1,entryX;ccds_transcript=true;clingen=1
请注意,您也可以使用带有GNU awk和gensub函数的组。这里不需要,但对于更复杂的替换可能有用

gensub提供了sub中不可用的附加功能 或gsub:在 替换文本。这是通过在regexp中使用括号来完成的 标记组件,然后在替换文本中指定“\N”, 其中N是1到9之间的数字

要回答您的评论:

假设您有以下输入:

1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;ccds_transcript=true;clingen=0
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1;ccds_transcript=true;clingen=1
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1;ccds_transcript=true;clingen=1;rejected=entry2
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1,entry2;ccds_transcript=true;clingen=1
您想添加entry2: -第一行没有接受字段 -第三个拒绝进入2 -第四个已经有entry2了

我调整了脚本以处理这些行:

awk -v entry="entry2" '
($2 == 9790725) && \
!($0 ~ "accepted=[^;]*" entry) && \ 
!($0 ~ "rejected=[^;]*" entry){
    if ($0 ~ /\;accepted=/){
        sub(/accepted=[^;]*/,"&," entry)
    } 
    else{
        sub(/$/,";accepted=" entry ";")
    }
}1' file
现在,awk将在附加条目之前检查条目是否已被接受或拒绝。如果需要不同的行为,请删除其中一个条件

1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;ccds_transcript=true;clingen=0;accepted=entry2;
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1,entry2;ccds_transcript=true;clingen=1
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1;ccds_transcript=true;clingen=1;rejected=entry2
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1,entry2;ccds_transcript=true;clingen=1
我认为文件的结构没有调整,它看起来像一个csv,有多个字段分隔符和列,有时不存在或顺序不同。使用json类型的结构和经过调整的工具来读取/更新它(而不是awk)会更容易


您还可以使用split函数在awk中处理此文件,并在=、;、、上拆分;,。我懒得尝试它,更喜欢更好的文件结构。

字符串函数文档:

$ cat tst.awk
{
    if ( match($0,/accepted=[^;]+/) ) {
        $0 = substr($0,1,RSTART+RLENGTH-1) ",entryX" substr($0,RSTART+RLENGTH)
    }
    else {
        $0 = $0 ";accepted=entryX"
    }
    print
}

$ awk -f tst.awk file
1       9790725 .       TTCCTCC T       .       .       ACMG=US;benign_cv=0;ccds_transcript=true;clingen=0;accepted=entryX
1       9790725 .       TTCCTCC T       .       .       ACMG=US;benign_cv=0;accepted=entry0,entry1,entryX;ccds_transcript=true;clingen=1
与sub:

如果替换中出现特殊字符“&”,则表示由regexp匹配的精确子字符串

结果:

1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;ccds_transcript=true;clingen=0;accepted=entryX;
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1,entryX;ccds_transcript=true;clingen=1
请注意,您也可以使用带有GNU awk和gensub函数的组。这里不需要,但对于更复杂的替换可能有用

gensub提供了sub中不可用的附加功能 或gsub:在 替换文本。这是通过在regexp中使用括号来完成的 标记组件,然后在替换文本中指定“\N”, 其中N是1到9之间的数字

要回答您的评论:

假设您有以下输入:

1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;ccds_transcript=true;clingen=0
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1;ccds_transcript=true;clingen=1
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1;ccds_transcript=true;clingen=1;rejected=entry2
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1,entry2;ccds_transcript=true;clingen=1
您想添加entry2: -第一行没有接受字段 -第三个拒绝进入2 -第四个已经有entry2了

我调整了脚本以处理这些行:

awk -v entry="entry2" '
($2 == 9790725) && \
!($0 ~ "accepted=[^;]*" entry) && \ 
!($0 ~ "rejected=[^;]*" entry){
    if ($0 ~ /\;accepted=/){
        sub(/accepted=[^;]*/,"&," entry)
    } 
    else{
        sub(/$/,";accepted=" entry ";")
    }
}1' file
现在,awk将在附加条目之前检查条目是否已被接受或拒绝。如果需要不同的行为,请删除其中一个条件

1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;ccds_transcript=true;clingen=0;accepted=entry2;
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1,entry2;ccds_transcript=true;clingen=1
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1;ccds_transcript=true;clingen=1;rejected=entry2
1   9790725 .   TTCCTCC T   .   .   ACMG=US;benign_cv=0;accepted=entry0,entry1,entry2;ccds_transcript=true;clingen=1
我认为文件的结构没有调整,它看起来像一个csv,有多个字段分隔符和列,有时不存在或顺序不同。使用json类型的结构和经过调整的工具来读取/更新它(而不是awk)会更容易


您还可以使用split函数在awk中处理此文件,并在=、;、、上拆分;,。我懒得尝试它,我更喜欢一个更好的文件结构。

谢谢@corentin!太好了!如果为了避免重复,我需要在添加前检查特定的userX是否已经在列表中,那又如何呢?我还有一个字段rejcted=user0,user1,…,userN,所以我不能只在字符串中搜索userX,因为它可能在拒绝字段中。对不起,如果我问的是一个次要问题,但这是我现在意识到的。无论如何,我都会接受你的回答。@cccnrc不确定是否理解。若用户已经被接受或拒绝,你们不应该在这两种情况下都添加它,对吗?我用一个能满足您需求的解决方案编辑。谢谢@corentin!太好了!如果为了避免重复,我需要在添加前检查特定的userX是否已经在列表中,那又如何呢?我还有一个字段rejcted=user0,user1,…,userN,所以我不能只操作
$ cat tst.awk
{
    if ( match($0,/accepted=[^;]+/) ) {
        $0 = substr($0,1,RSTART+RLENGTH-1) ",entryX" substr($0,RSTART+RLENGTH)
    }
    else {
        $0 = $0 ";accepted=entryX"
    }
    print
}

$ awk -f tst.awk file
1       9790725 .       TTCCTCC T       .       .       ACMG=US;benign_cv=0;ccds_transcript=true;clingen=0;accepted=entryX
1       9790725 .       TTCCTCC T       .       .       ACMG=US;benign_cv=0;accepted=entry0,entry1,entryX;ccds_transcript=true;clingen=1

在字符串中搜索userX,因为它可能位于拒绝字段中。对不起,如果我问的是一个次要问题,但这是我现在意识到的。无论如何,我都会接受你的回答。@cccnrc不确定是否理解。若用户已经被接受或拒绝,你们不应该在这两种情况下都添加它,对吗?我用一个适合您需要的解决方案进行了编辑。