【问题标题】:Use grep to select certain words with special characters使用 grep 选择某些带有特殊字符的单词
【发布时间】:2021-12-26 04:16:46
【问题描述】:

我有一个如下所示的文件:

chr4    StringTie   exon    185054979   185055237   1000    +   .   gene_id `"MSTRG.41311"; transcript_id "ENST00000658673.1"; exon_number "2"; gene_name `"LINC02436"; ref_gene_id "ENSG00000250754.6";
chr4    StringTie   exon    185069961   185070030   1000    +   .   gene_id `"MSTRG.41311"; transcript_id "ENST00000658673.1"; exon_number "3"; gene_name "LINC02436"; ref_gene_id "ENSG00000250754.6";
chr6    HAVANA  exon    169067764   169068299   .   +   .   gene_id "ENSG00000234519.2"; transcript_id "ENST00000666733.1"; exon_number "1"; gene_name "RP3-495K2.1";

我只想保留基因 id 信息,因此文件将如下所示:

MSTRG.41311
MSTRG.41311
ENSG00000234519.2

我尝试了以下方法:

cat file.gtf|sed 's/!ENSG*//g'|sed 's/!ENSG*//g' > myfile.txt.

但这并没有给我想要的输出。我认为这是因为引号是一个特殊字符,但我不确定。 有人可以帮忙解决这个问题吗?

谢谢!

【问题讨论】:

    标签: sed grep


    【解决方案1】:

    试试这个(GNU sed):

    sed -E 's/gene_id/\x0/;s/.*\x0 `?"([^"]+)".*/\1/' input
    

    由于gene_id 在前两行出现两次(而且您似乎对每行的第一次出现感兴趣),我不能只使用sed 's/.*gene_id…,否则.* 会吃光所有东西到 last gene_id 之前就行了。

    因此,我的方法是选择每行的第一个 gene_id 并通过 s/gene_id/\x0/ 将其更改为 \x0 字符(因为在 gene_id 之前没有贪婪的 .*,它将匹配第一个就行了)。

    一旦我用\x0 标记了那个位置,我就可以用它在下面的substitution 中“锚定”正则表达式的其余部分,其中.*\x0 将匹配每行上的所有内容,包括(什么是)第一个gene_id 上线,`?"([^"]+)".* 匹配行的其余部分,同时使用(…) 捕获"s 之间的部分。


    我已将-E 用于扩展正则表达式,因此我可以使用(…) 代替\(…\)

    哦,`? 只是因为您已将这些反引号放在前两行,所以使用 ?(如果没有 -E 选项,则为 \?)我需要零或一反引号匹配该位置。不知道是不是复制粘贴错误。

    【讨论】:

      【解决方案2】:

      你也可以试试 cut -d"delimiter" -f columns nb

      例如:

      cat file.gtf | cat f.txt | cut -d"\"" -f 1
      

      使用\是因为“不能放在其他两个之间”

      【讨论】:

        【解决方案3】:

        使用sed

        $ sed 's/.*\bgene_id[^"]*.\([^"]*\).*/\1/' input_file
        MSTRG.41311
        MSTRG.41311
        ENSG00000234519.2
        

        .*\bgene_id[^"]*. - 匹配 gene_id.." 并从分组中排除

        \([^"]*\) - 在组中捕获从最后一场比赛到下一次出现" 双引号的所有内容。这个匹配可以返回返回引用\1

        .* - 排除其他所有内容

        【讨论】:

          【解决方案4】:

          这可能对你有用(GNU sed):

          sed -En 's/.*\<gene_id\>[^"]*"([^"]*)".*/\1/p' file
          

          打开扩展正则表达式 -E 并关闭隐式打印 -n,因为这是一个过滤操作。

          匹配单词gene_id,对下一对双引号之间的字符串进行反向引用,并用打印结果的反向引用替换整行。

          【讨论】:

            【解决方案5】:

            快速:

            awk -v RS='[^[:alnum:]_.]+' 'f==1{print;f=0} $0=="gene_id"{f=1}'
            

            100% POSIX:

            awk -F '[^[:alnum:]_.]+' '{for (i=1; i<=NF; i++) {if ($i=="gene_id") {print $(i+1); next}}}'
            

            将 RS 设置为正则表达式不是 posix,但通常可用。 您可以调整其中一个以打印行中任何位置的任何字段。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-05-30
              • 1970-01-01
              • 2017-03-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多