【问题标题】:awk match and find mismatch between files and output resultsawk 匹配并查找文件和输出结果之间的不匹配
【发布时间】:2016-08-27 23:50:46
【问题描述】:

在下面的awk 中,我使用$5 $7$8file1 来搜索$3 $5$6file2。标题行被跳过,然后输出一个新文件,其中包含哪些行匹配,如果它们与file 不匹配,则匹配缺失。当我搜索一个匹配项时,使用 3 个字段作为查找的键并且不要跳过标题我得到current output。对于这篇长文和file examples,我深表歉意,我只是想把一切都包括在内,以帮助实现这一目标。谢谢你:)。

文件1

 Index  Chromosomal Position    Gene    Inheritance Start   End Ref Alt Func.refGene
98  48719928    FBN1    AD  48719928    48719929    AT  -   exonic
101 48807637    FBN1    AD  48807637    48807637    C   T   exonic

文件2

R_Index Chr Start   End Ref Alt Func.IDP.refGene
36  chr15   48719928    48719929    AT  -   exonic
37  chr15   48719928    48719928    A   G   exonic
38  chr15   48807637    48807637    C   T   exonic

awk

awk -F'\t' '
    NR == FNR {
            A[$25]; A[$26]; A[$27]
            next
    }
    {
            B[$3]; B[$5]; B[$6]
    }
    END {
            print "Match"
            OFS=","
            for ( k in A )
            {
                    if ( k && k in B )
                            printf "%s ", k
            }

            print "Missing from file1"
            OFS=","
            for ( k in B )
            {
                    if ( ! ( k in A ) )
                            printf "%s ", k
            }

            print "Missing from file2"
            OFS=","
            for ( k in A )
            {
                    if ( ! ( k in B ) )
                            printf "%s ", k
            }
    }
' file1 file2 > list

电流输出

Match
Missing from file1
A C Ref 48807637 Alt Start T G - AT 48719928 Missing from file2

期望的输出

Match 48719928 AT -, 48807637 C T
Missing from file1 48719928 A G
Missing from file2

【问题讨论】:

  • 去掉数组元素之间的空格
  • 删除空间确实允许awk 运行,但输出不正确(似乎是一个包含原始数据和一些附加数据的文件)......我发布了它作为编辑。谢谢你:)。
  • current output 1 代表什么?您的脚本有语法错误,它不能产生任何输出。 Edit 代表什么?只需显示具有清晰、简洁、可测试的样本输入和预期输出的 minimal reproducible example

标签: awk


【解决方案1】:

您误解了 awk 语法并将 awk 与 shell 混淆了。当你写的时候:

A[$25] [$26] [$27]

你的意思可能是:

A[$25]; A[$26]; A[$27]

(对于B[] 也是如此)以及当你写的时候:

IFS=

因为 IFS 是一个 shell 变量,而不是一个 awk 变量,所以你可能的意思是

FS=

但是,因为您在 END 部分执行此操作,而不是调用 split(),因此不做任何会使用 FS 的事情,因此您希望通过它实现。也许你的意思是:

OFS=

但是你没有做任何会使用 OFS 的事情,而且你想要的输出不是逗号分隔的,所以你也想知道你希望用它实现什么。

如果这些信息不足以让您自己解决问题,那么请将您的示例减少到 10 列或更少的内容,这样我们就不必阅读大量不相关的信息来帮助您。

【讨论】:

  • 我清理了帖子,“awk”现在运行了(我很困惑awk syntax with shell)。唯一的输出是结果,我取出了edit。非常感谢:)。
  • 不客气。现在只需将您的print ks 更改为printf "%s ", ks,您就差不多完成了。这样做然后让我们知道您是否需要更多帮助。
  • 我用输出更新了帖子,printf "%s ", k 是做什么的?谢谢你:)。
  • 指定一个逗号被打印分隔的多个字符串。感谢您的所有帮助:)。
  • 不客气,但不,它没有这么说。如果您要学习使用 awk,我建议您阅读 Arnold Robbins 的《Effecitve Awk Programming, 4th Edition》一书,它会为您节省大量的试错时间,并且是一个很好的参考资料。
【解决方案2】:

程序 1

这可行,除了输出格式与您要求的不同:

awk 'FNR==1 { next }
     FNR == NR { file1[$5,$7,$8] = $5 " " $7 " " $8 }
     FNR != NR { file2[$3,$5,$6] = $3 " " $5 " " $6 }
     END { print "Match:"; for (k in file1) if (k in file2) print file1[k] # Or file2[k]
           print "Missing in file1:"; for (k in file2) if (!(k in file1)) print file2[k]
           print "Missing in file2:"; for (k in file1) if (!(k in file2)) print file1[k]
     }' file1 file2

输出 1

Match:
48807637 C T
48719928 AT -
Missing in file1:
48719928 A G
Missing in file2:

程序 2

如果您必须将类别中的每组值用逗号分隔在一行中,则:

awk 'FNR==1 { next }
     FNR == NR { file1[$5,$7,$8] = $5 " " $7 " " $8 }
     FNR != NR { file2[$3,$5,$6] = $3 " " $5 " " $6 }
     END {
            printf "Match"
            pad = " "
            for (k in file1)
            {
                if (k in file2)
                {
                    printf "%s%s", pad, file1[k]
                    pad = ", "
                }
            }
            print ""

            printf "Missing in file1"
            pad = " "
            for (k in file2)
            {
                if (!(k in file1))
                {
                    printf "%s%s", pad, file2[k]
                    pad = ", "
                }
            }
            print ""

            printf "Missing in file2"
            pad = " "
            for (k in file1)
            {
                if (!(k in file2))
                {
                    printf "%s%s", pad, file1[k]
                    pad = ", "
                }
            }
            print ""
     }' file1 file2

代码有点大,但使用的格式加剧了差异。更改全部在 END 块中;其他代码不变。 END 块中的动作序列不再适合单行,因此为了便于阅读,它们被分散开来。如果需要,您可以应用大量分号并将行连接起来以缩小程序的外观大小。

尝试打印功能很诱人,但我认为条件太复杂了,不值得一试——但我愿意接受其他建议。

输出 2

Match 48807637 C T, 48719928 AT -
Missing in file1 48719928 A G
Missing in file2

这个输出比第一个显示的更难解析,所以用它自动做任何事情都会很棘手。虽然只有 3 个条目需要担心,但行长不是问题。如果达到 300 万个条目,那么行会变得非常长且难以管理。

【讨论】:

  • 感谢大家的帮助和解释,我非常感谢他们 :) @Jonathan Leffler 程序 1 效果很好 :)
猜你喜欢
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 2021-12-26
  • 2017-07-01
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
  • 2012-11-14
相关资源
最近更新 更多