【问题标题】:awk sub in specified columnawk sub 在指定列中
【发布时间】:2016-03-22 11:42:52
【问题描述】:

我正在尝试删除不同分隔符前后的文本,仅在特定列中,第 3 列。

第一个分隔符是分号,第二个是逗号。它们也存在于未显示的列中。

输入数据:

chr2L   54273   2L_54273_SNP;rs203207895        A       G       999     PASS    ALTCOUNT=118;DB;REFCOUNT=69     GT      ./.     ./.     0/0 
chr2L   54339   2L_54339_SNP;rs206877787,rs80377533     T       A       999     PASS    ALTCOUNT=114;DB;REFCOUNT=73     GT      ./.     ./.  
chr2L   54587   2L_54587_SNP;rs203534836        A       G       999     PASS    ALTCOUNT=5;DB;REFCOUNT=199      GT      0/0     0/0     0/0  

需要的输出:

chr2L   54273   rs203207895        A       G       999     PASS    ALTCOUNT=118;DB;REFCOUNT=69     GT      ./.     ./.     0/0 
chr2L   54339   rs206877787     T       A       999     PASS    ALTCOUNT=114;DB;REFCOUNT=73     GT      ./.     ./.  
chr2L   54587   rs203534836        A       G       999     PASS    ALTCOUNT=5;DB;REFCOUNT=199      GT      0/0     0/0     0/0  

我的工作重点是仅删除分号之前(包括)之前的文本,但没有显着效果:

awk '{ if ($3 == ".*\;//") {$3 = ""; print} else { print }; }' < a > b
sed 's/.*;//' a > b
awk '{ sub(/*.;/,"",$3) }1 ' < a > b
awk '{sub(;/./*,""); print}' < a > b

【问题讨论】:

    标签: bash awk substitution


    【解决方案1】:

    我认为你可以使用这样的东西:

    awk '{ gsub(/^.*;|,.*$/, "", $3) }1' file
    

    这匹配从第三个字段的开头到分号或从逗号到字段结尾的任何内容,并将它们替换为空字符串。

    您的一个问题是您使用的是*.(语法不正确)而不是.*(零个或多个任意字符)。

    按照 cmets 中的建议(谢谢),您可能希望使模式更加严格,例如:

    /^[^;]*;|,[^,]*$/
    

    仅匹配从开始到第一个 ; 和从最后一个 , 到结束。如果您确定您的数据始终只有一个; 和一个,,这不是必需的,但需要注意。

    如果您的输入是制表符分隔的,那么您可以通过指示 awk 来保留空格:

    awk 'BEGIN { FS = OFS = "\t" } { gsub(/^.*;|,.*$/, "", $3) } 1' file
    

    FSOFS 是用于设置输入和输出字段分隔符的变量。

    【讨论】:

    • 对,只是为了完整性,因为它可能对 OP 给出他/她的样本数据无关紧要 - 上面将删除到最后一个分号和第一个逗号,而 gsub(/^[^;]*;|,[^,]*$/, "", $3) 将删除到第一个分号和最后一个逗号。此外,为了保留空白,OP 可以对整条记录而不是一个字段进行操作 sub(/[^[:space:]]+;/,""); sub(/,[^[:space:]]+/,"")
    • @Ed 谢谢,已更新以包含您的建议并添加一个看起来很讨厌的 sed 选项来保留空格。
    • @EdMorton @TomFenech 感谢您的帮助。我使用awk '{ gsub(/^.*;|,.*$/, "", $3) }1' &lt; a | awk '{gsub(" ","\t");print}' &gt; b 进行了调查,因为输入文件实际上是制表符分隔的。 sed -E 's/^(([^ ]+ +){2})[^;]+;([^,]+)(,[^ ]+)*/\1\3/' a > b 没有改变任何东西,即使用 \t 替换空格也是如此。
    • @Sarah 您的管道相当于将热水器的输出连接到第二个热水器的输入以获得更温暖的水。不要那样做,把原来的热水器换成更好的热水器。在这种情况下,只需在 awk 脚本的前面添加 BEGIN{FS=OFS="\t"},这样 awk 就会知道您的输入和输出是制表符分隔的。并且不要使用输入重定向,因为它会阻止 awk 使用 FILENAME 并且不能扩展到 2 个或更多输入文件。使用awk 'BEGIN{FS=OFS="\t"} { gsub(/^.*;|,.*$/,"",$3) }1' a
    • 不确定我是否理解(*plumped... plummed???),但这个词是plumbed,源自法语单词plomb,意思是lead(金属发音为“led”),因为回到了水管等由铅制成,因此安装它们的人被称为管道工/管道工。
    猜你喜欢
    • 2020-06-24
    • 1970-01-01
    • 2017-07-09
    • 2013-12-06
    • 2020-07-14
    • 2013-07-10
    • 1970-01-01
    • 2014-08-01
    • 1970-01-01
    相关资源
    最近更新 更多