gawk / sed:找到一行并替换第3列

时间:2015-04-06 19:23:29

标签: unix sed gawk

我有一个文件:

rs4648841   chr1    2365885 --  A   T   0.40095 0.228978043022122   chr1:2523811
rs4648843   chr1    2366316 --  T   C   0.15694 0.5736208829426915  chr1:2523811
rs61763906  chr1    2366517 --  A   G   0.07726 0.5566728930776897  chr1:2523811

我需要在第一列中找到“rs4648843”,一旦我找到包含它的行,我想将此行中的第4列编辑为“ADS”(使用sed,gawk并不重要)

尝试过:(但当然没有用)

sed '/rs4648843/p' input | sed 's//ADD/g' 

修改 我不需要创建新文件,我想编辑我已经存在的文件。

3 个答案:

答案 0 :(得分:1)

试试这个:

awk '/^rs4648843/ {$4="ADS"}1' file | column -t

输出:

rs4648841   chr1  2365885  --   A  T  0.40095  0.228978043022122   chr1:2523811
rs4648843   chr1  2366316  ADS  T  C  0.15694  0.5736208829426915  chr1:2523811
rs61763906  chr1  2366517  --   A  G  0.07726  0.5566728930776897  chr1:2523811

答案 1 :(得分:1)

使用awk

假设您的输入文件是以制表符分隔的:

$ awk -v OFS="\t" '$1=="rs4648843"{$4="ADS"} 1' file
rs4648841       chr1    2365885 --      A       T       0.40095 0.228978043022122       chr1:2523811
rs4648843       chr1    2366316 ADS     T       C       0.15694 0.5736208829426915      chr1:2523811
rs61763906      chr1    2366517 --      A       G       0.07726 0.5566728930776897      chr1:2523811

要更改现有文件:

awk -v OFS="\t" '$1=="rs4648843"{$4="ADS"} 1' file >file.tmp && mv file.tmp file

使用sed

再次,假设以制表符分隔的输入,就地更改文件:

sed -i -r '/^rs4648843/ {s/(([^\t]*\t){3})[^\t]+/\1ADS/}' file

以上是对GNU sed的测试。对于OSX(BSD)sed,请尝试:

sed -i .bak -E '/^rs4648843/ {s/(([^\t]*\t){3})[^\t]+/\1ADS/;}' file

使用awk但传递rs...值作为变量

awk -v rs="rs4648843" -v OFS="\t" '$1==rs{$4="ADS"} 1' file

使用带有斜杠的字符串的sed

根据评论,假设我们想要替换ADS,而不是TRAF6-RAG1/2。由于它包含/字符,因此会混淆上面给出的sed命令。有两种可能的解决方案:一种是用反斜杠转义/。其工作原理如下:

sed -r '/^rs4648843/ {s/(([^\t]*\t){3})[^\t]+/\1TRAF6-RAG1\/2/}' file

另一种解决方案是为替换命令使用不同的标记。 sed的替换命令通常以s/old/new/的形式编写,但除了/之外的其他标记也是可能的。例如,以下使用竖线|作为标记而不是/,从而适应新字符串:

sed -r '/^rs4648843/ {s|(([^\t]*\t){3})[^\t]+|\1TRAF6-RAG1/2|}' file

答案 2 :(得分:1)

假设您的数据看起来是固定宽度:

gawk -v item=rs4648843 '
    BEGIN {
        FIELDWIDTHS="12 8 8 4 4 4 8 20 12"
        OFS=""
        pattern = "^"item"\\\>" 
    }
    $1 ~ pattern {$4 = sprintf("%-4s", "ADS")} 
    1
' file
rs4648841   chr1    2365885 --  A   T   0.40095 0.228978043022122   chr1:2523811
rs4648843   chr1    2366316 ADS T   C   0.15694 0.5736208829426915  chr1:2523811
rs61763906  chr1    2366517 --  A   G   0.07726 0.5566728930776897  chr1:2523811

要就地编辑文件,我们可以使用ed

rs="rs4648843"
ed file <<END_ED
g/^$rs\>/ s/^\(\([^[:blank:]]\+[[:blank:]]\+\)\{3\}\)[^[:blank:]]\+/\1ADS/
w
q
END_ED

冗长的正则表达式捕获前3个以空格分隔的单词,并用“ADS”替换第4个单词