用于解析文件的 awk 命令

用于解析文件的 awk 命令

我有一个以下文本文件。我正在向您展示前 3 行。

chrom   st  end gene    strand  c1  c2  c3  c4  c5  c6  c7  c8  c9  c10 c11 c12 c13 c14
chr6    3345    3543    geneA   +   36  -23 -1  3   1250    946 416 458 475 417 58  80  2   14
chr9    1302    1389    geneB   -   8   -10 -18 -8  2896    2128    635 955 372 385 -20 31  -7  -7

我想按原样打印出第一行,因为它是标题行。

然后对于后续行(即从第 2 行开始),我想按原样打印前 5 个字段(直到链信息),之后如果该字段(从第 6 个字段开始)的值 >= 100 则打印该值照原样,如果该字段的值 < 100,只需将其替换为 NA。

所以我的输出文件应该看起来像这样(理想情况下,制表符分隔)

chrom   st  end gene    strand  c1  c2  c3  c4  c5  c6  c7  c8  c9  c10 c11 c12 c13 c14
chr6    3345    3543    geneA   +   NA  NA  NA  NA  1250    946 416 458 475 417 NA  NA  NA  NA
chr9    1302    1389    geneB   -   NA  NA  NA  NA  2896    2128    635 955 372 385 NA  NA  NA  NA

答案1

awk 'NR > 1 { for (i = 6; i <= NF; i++) if ($i < 100) $i = "NA" }; 1' yourfile.txt

扩展评论:

NR > 1 {                         # skipping NR == 1, the first line
    for (i = 6; i <= NF; i++)    # column 6 to the end, skipping first 5
        if ($i < 100) $i = "NA"  # self-explanatory
}

1 # print all lines; 1 evaluates to true, and default action is print

编辑:有多种设置方法OFS。我能想到的最简洁的方法是OFS='\t'在文件名之前添加。

awk '...' OFS='\t' file.txt
awk -v OFS='\t' '...' file.txt
awk 'BEGIN { OFS="\t" }; ...' file.txt

答案2

jw013 已经为您提供了一个很好的 awk 解决方案,但是自从您提到 Perl 以来:

perl -lane 'map{$_="NA" if $_<100}@F[5..$#F] if $.>1; print join "\t", "@F"' file 

解释

  • perl -lane:处理每个输入行 ( -n) 并将其按空格分割到@F数组 ( -a) 中,然后运行 ​​给出的脚本-e。从每行中删除尾随换行符,并向每个语句-l添加。\nprint

  • map{$_="NA" if $_<100}@F[5..$#F]:对于数组中@F 从第 6 个到末尾的每个元素(字段),如果小于 100,则将该元素更改为“NA”。

  • if $.>1;:前面的内容map{}只会运行这不是第一行。

  • print join "\t", "@F"'@F使用选项卡连接数组的每个元素(在对 jw013 的答案的评论中要求)并打印它。

答案3

sed '1n;s|$| |;:na
    s|\([+-] .*\) [+-]*[0-9]\{1,2\} |\1 NA |
    t na;s| $||'

从您显示的数据来看,sed s///;t我认为这个小功能没有理由不起作用。(感谢 jw013 指出可能错过的最后一栏。)这只是将+/-一行中 a 后面的每 1 或 2 个字符的数字字符串替换为它之前的所有内容,NA直到没有更多的内容可以替换。

这是另一个没有递归的版本,它利用了sedh空间:

sed '1n;h;s|.*[+-] ||;s|$| |
    s| [+-]*[0-9]\{1,2\} | NA |g
    x;G;s|\([+-] *\).*\n|\1|;s| $||'

它依赖于相同的标记,并在那里分割线 - 前半部分在h旧空间中保持不变,而从模式空间中完全删除。然后,我们对所有 1,2 个数字字符单词进行全局替换,附加到h旧空格,更改x模式和旧空格,并删除作为附加操作结果插入的h标记和 ewline 之间的所有内容。\n

相关内容