【问题标题】:How to search for string with one variable position in the string?如何在字符串中搜索具有一个变量位置的字符串?
【发布时间】:2020-12-05 01:20:04
【问题描述】:

我想在一个大文件中查找所有行,其中包含一个字符串,并允许我的字符串中的一个字符不同,并且仍然认为它是匹配的。

例如我有这个文件:

>1 agctcaTATAAGtataagctagaagta
>2 gatgctagcgaagtaatgc
>3 atatagcgctagagccgtagta
>4 gctagcaTATCAGgatgtagtagta
...

这个字符串:tataag,所以我得到这个输出:

>1 agctcaTATAAGtataagctagaagta
>4 gctagcaTATCAGgatgtagtagta

因为第 1 行直接匹配,而第 4 行匹配除了字母 A 之外的所有内容,其中它有一个 C

【问题讨论】:

  • 查看 agrep:在文件中搜索字符串或正则表达式,并具有近似匹配功能
  • 请在您的问题中以代码的形式添加您的努力,然后让我们知道,非常鼓励这样做。
  • agrep 的手册页看起来很不错,但我的 mac 上安装失败...

标签: search awk grep full-text-search


【解决方案1】:

允许一个字符不同:

$ cat tst.awk
BEGIN {
    lgth = length(str)
    for (i=1; i<=lgth; i++) {
        head = esc(substr(str,1,i-1))
        tail = esc(substr(str,i+1))
        part = head "." tail
        reg  = (i>1 ? reg "|" : "") part
    }
    reg = "(" tolower(reg) ")"
    printf "Searching for string \"%s\"\n", str | "cat>&2"
    printf "Searching for regexp \"%s\"\n", reg | "cat>&2"
}
tolower($0) ~ reg

function esc(str) {
    gsub(/[^^\\]/,"[&]",str)
    gsub(/\^|\\/,"\\\\&",str)
    return str
}

.

$ awk -v str='tataag' -f tst.awk file
>1 agctcaTATAAGtataagctagaagta
>4 gctagcaTATCAGgatgtagtagta
Searching for string "tataag"
Searching for regexp "(.[a][t][a][a][g]|[t].[t][a][a][g]|[t][a].[a][a][g]|[t][a][t].[a][g]|[t][a][t][a].[g]|[t][a][t][a][a].)"

允许缺少一个字符:

$ cat tst.awk
BEGIN {
    lgth = length(str)
    for (i=1; i<=lgth; i++) {
        head = esc(substr(str,1,i))
        tail = esc(substr(str,i+1))
        part = head "?" tail
        reg  = (i>1 ? reg "|" : "") part
    }
    reg = "(" tolower(reg) ")"
    printf "Searching for string \"%s\"\n", str | "cat>&2"
    printf "Searching for regexp \"%s\"\n", reg | "cat>&2"
}
tolower($0) ~ reg

function esc(str) {
    gsub(/[^^\\]/,"[&]",str)
    gsub(/\^|\\/,"\\\\&",str)
    return str
}

.

$ awk -v str='tataag' -f tst.awk file
>1 agctcaTATAAGtataagctagaagta
>3 atatagcgctagagccgtagta
Searching for string "tataag"
Searching for regexp "([t]?[a][t][a][a][g]|[t][a]?[t][a][a][g]|[t][a][t]?[a][a][g]|[t][a][t][a]?[a][g]|[t][a][t][a][a]?[g]|[t][a][t][a][a][g]?)"

以上所有转义都是为了确保您的字符串被视为文字字符串,即使/当它包含正则表达式元字符时也是如此。

完成测试后,您可以删除 2 个打印语句。

【讨论】:

    【解决方案2】:
    $ # generate the different combinations
    $ # assumes search term doesn't have regex metacharacters
    $ echo 'tataag' | awk 'BEGIN{FS=OFS=""} {orig=$0; for(i=1;i<=NF;i++)
                           { $i = "."; ORS=(i==NF)?"\n":"|"; print; $0=orig }}'
    .ataag|t.taag|ta.aag|tat.ag|tata.g|tataa.
    
    $ # pass it to grep as the regex to be used
    $ echo 'tataag' | awk 'BEGIN{FS=OFS=""} {orig=$0; for(i=1;i<=NF;i++)
                           { $i = "."; ORS=(i==NF)?"\n":"|"; print; $0=orig }}' | grep -iEf - ip.txt
    >1 agctcaTATAAGtataagctagaagta
    >4 gctagcaTATCAGgatgtagtagta
    

    您也可以通过使用[acgt] 而不是. 来使其更严格

    $ echo 'tataag' | awk 'BEGIN{FS=OFS=""} {orig=$0; for(i=1;i<=NF;i++)
                           { $i = "[acgt]"; ORS=(i==NF)?"\n":"|"; print; $0=orig }}'
    [acgt]ataag|t[acgt]taag|ta[acgt]aag|tat[acgt]ag|tata[acgt]g|tataa[acgt]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-01
      • 1970-01-01
      • 2020-06-25
      • 2021-11-28
      • 1970-01-01
      相关资源
      最近更新 更多