正则表达式匹配,尽管一些字符不匹配模式?

时间:2018-04-12 22:54:06

标签: regex bash awk sed bioinformatics

我正在使用一些生物信息学数据,我有这个sed表达式:

sed -n 'N;/.*:\(.*\)\n.*\1/{p;n;p;n;p};D' file.txt

它目前采用的结构如下:

@E00378:1485 1:N:0:ABC
ABCDEF ##should match, all characters present
+
#
@E00378:1485 1:N:1:ABC
XYZABX ##should match, with permutation
+
#
@E00378:1485 1:N:1:ABCDE
ZABCDXFGH ##should match, with permutation
+
#
@E00378:1485 1:N:1:CBA 
ABC ##should not match, order not preserved
+
#

如果在第二行中找到:之后的序列,则返回4行,所以在这种情况下我会得到:

@E00378:1485 1:N:0:ABC
ABCDEF
+
#

但是,我希望通过添加搜索字母的任何单个排列的可能性来扩展我的搜索,同时保持顺序,例如ABXZBC,{{ 1}},AHC都符合搜索条件ABO

像这样的搜索可以构建为单行吗?或者我应该写一个脚本吗?

我原以为应该可以以编程方式将其中一个字母更改为模式空间中的ABC

我试图按照AWK模式的方式制作一些匹配定义为:

的模式
*

但我似乎无法弄清楚如何以编程方式为p = ""; p = p "."a[2]a[3]a[4]a[5]a[6]a[7]a[8]"|"; p = p a[1]"."a[3]a[4]a[5]a[6]a[7]a[8]"|"; p = p a[1]a[2]"."a[4]a[5]a[6]a[7]a[8]"|"; p = p a[1]a[2]a[3]"."a[5]a[6]a[7]a[8]"|"; p = p a[1]a[2]a[3]a[4]"."a[6]a[7]a[8]"|"; p = p a[1]a[2]a[3]a[4]a[5]"."a[7]a[8]"|"; p = p a[1]a[2]a[3]a[4]a[5]a[6]"."a[8]"|"; p = p a[1]a[2]a[3]a[4]a[5]a[6]a[7]"."; m = p; 数字制作它。

2 个答案:

答案 0 :(得分:1)

好的,请查看上面输入fuzzy的地方:

£ perl -0043 -MText::Fuzzy -ne 'if (/.*:(.*?)\n(.*?)\n/) {my ($offset, $edits, $distance) = Text::Fuzzy::fuzzy_index ($1, $2); print "$offset $edits $distance\n";}' fuzzy
3 kkk 0
5 kkd 1
5 kkkkd 1

由于您没有100%明确“模糊”标准(并且在您拥有测量工具之前不能这样做),我将首先解释一下。参考这里: http://search.cpan.org/~bkb/Text-Fuzzy-0.27/lib/Text/Fuzzy.pod

基本上,对于每个记录(我假设它在#上被分割为-0043位),输出是一个偏移量,第一个字符串如何成为第二个字符串,并且最后是两个字符串之间的“距离”(Levenshtein,我会假设)。

所以..

£ perl -0043 -MText::Fuzzy -ne 'if (/.*:(.*?)\n(.*?)\n/) {my ($offset, $edits, $distance) = Text::Fuzzy::fuzzy_index ($1, $2); print "$_\n" if $distance < 2;}' fuzzy
@E00378:1485 1:N:0:ABC
ABCDEF
+
#

@E00378:1485 1:N:1:ABC
XYZABX
+
#

@E00378:1485 1:N:1:ABCDE
ZABCDXFGH
+
#

请参阅此处以安装像Text :: Fuzzy这样的perl模块 https://www.thegeekstuff.com/2008/09/how-to-install-perl-modules-manually-and-using-cpan-command/

无法打印的记录的输入/输出示例(距离为3):

@E00378:1485 1:N:1:ABCDE
ZDEFDXFGH
+
#

给我们这个(或者根本不用第二个perl命令打印)

3 dddkk 3

答案 1 :(得分:1)

Awk 没有 sed 反向引用,但具有更强的表现力来弥补差异。以下脚本组成了从引导线的最后一个字段进行匹配的模式,然后将模式应用于后续行。

#! /usr/bin/awk -f

BEGIN {
    FS = ":"
}

# Lead Line has 5 fields
NF == 5 {
    line0 = $0
    seq = $NF
    getline
    if (seq != "") {
        n = length(seq)
        if (n == 1) {
            pat = seq
        } else {
            # ABC -> /.BC|A.C|AB./
            pat = "." substr(seq, 2, n - 1)
            for (i = 2; i < n; ++i)
                pat = pat "|" substr(seq, 1, i - 1) "." substr(seq, i + 1, n - i)
            pat = pat "|" substr(seq, 1, n - 1) "."
        }
        if ($0 ~ pat) {
            print line0
            print
            getline; print
            getline; print
            next
        }
    }
    getline
    getline
}

如果以上需要一些工作来形成不同的匹配模式,我们大多限制我们对模式组合线的修改。顺便说一句......我注意到序列重复 - 为了加快速度,我们可以实现缓存:

#! /usr/bin/awk -f

BEGIN {
    FS = ":"
    # Noticed that sequences repeat
    # -- implement caching of patterns
    split("", cache)
}

# Lead Line has 5 fields
NF == 5 {
    line0 = $0
    seq = $NF
    getline
    if (seq != "") {
        if (seq in cache) {
            pat = cache[seq]
        } else {
            n = length(seq)
            if (n == 1) {
                pat = seq
            } else {
                # ABC -> /.BC|A.C|AB./
                pat = "." substr(seq, 2, n - 1)
                for (i = 2; i < n; ++i)
                    pat = pat "|" substr(seq, 1, i - 1) "." substr(seq, i + 1, n - i)
                pat = pat "|" substr(seq, 1, n - 1) "."
            }
            cache[seq] = pat
        }
        if ($0 ~ pat) {
            print line0
            print
            getline; print
            getline; print
            next
        }
    }
    getline
    getline
}