awk:基于多种模式的日志处理

awk: log processing based on multiple patterns

我正在处理的日志文件由从不同样本(标识为浮点数 1.1、1.2 ... 1.14)中获取的一些测量值组成,这些测量值按以下格式排列:

Finding intramodel H-bonds
Constraints relaxed by 0.5 angstroms and 20 degrees
Models used:
    1.1 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.2 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.3 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.4 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.5 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.6 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.7 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.8 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.9 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.10 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.11 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.12 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.13 SarsCov2_structure19R_nsp5holo_rep1.pdb
    1.14 SarsCov2_structure19R_nsp5holo_rep1.pdb

16 H-bonds
H-bonds (donor, acceptor, hydrogen, D..A dist, D-H..A dist):
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.1/? HIS 163 NE2   SarsCov2_structure19R_nsp5holo_rep1.pdb #1.1/A UNL 888 S   no hydrogen                                                   3.850  N/A
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.1/? GLU 166 N     SarsCov2_structure19R_nsp5holo_rep1.pdb #1.1/A UNL 888 O   SarsCov2_structure19R_nsp5holo_rep1.pdb #1.1/? GLU 166 H      2.909  2.070
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.1/A UNL 888 N     SarsCov2_structure19R_nsp5holo_rep1.pdb #1.1/? CYS 44 O    SarsCov2_structure19R_nsp5holo_rep1.pdb #1.1/A UNL 888 H      2.798  1.892
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.2/? GLN 189 NE2   SarsCov2_structure19R_nsp5holo_rep1.pdb #1.2/A UNL 888 S   SarsCov2_structure19R_nsp5holo_rep1.pdb #1.2/? GLN 189 1HE2   3.896  2.916
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.3/? GLU 166 N     SarsCov2_structure19R_nsp5holo_rep1.pdb #1.3/A UNL 888 O   SarsCov2_structure19R_nsp5holo_rep1.pdb #1.3/? GLU 166 H      2.673  1.892
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.3/A UNL 888 N     SarsCov2_structure19R_nsp5holo_rep1.pdb #1.3/? CYS 44 O    SarsCov2_structure19R_nsp5holo_rep1.pdb #1.3/A UNL 888 H      3.071  2.338
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.4/? HIS 163 NE2   SarsCov2_structure19R_nsp5holo_rep1.pdb #1.4/A UNL 888 S   no hydrogen                                                   3.927  N/A
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.4/A UNL 888 N     SarsCov2_structure19R_nsp5holo_rep1.pdb #1.4/? THR 190 O   SarsCov2_structure19R_nsp5holo_rep1.pdb #1.4/A UNL 888 H      3.029  2.173
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.8/? GLN 189 NE2   SarsCov2_structure19R_nsp5holo_rep1.pdb #1.8/A UNL 888 S   SarsCov2_structure19R_nsp5holo_rep1.pdb #1.8/? GLN 189 2HE2   3.631  2.751
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.9/? CYS 145 N     SarsCov2_structure19R_nsp5holo_rep1.pdb #1.9/A UNL 888 O   SarsCov2_structure19R_nsp5holo_rep1.pdb #1.9/? CYS 145 H      2.966  2.210
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.9/A UNL 888 N     SarsCov2_structure19R_nsp5holo_rep1.pdb #1.9/? ARG 188 O   SarsCov2_structure19R_nsp5holo_rep1.pdb #1.9/A UNL 888 H      3.067  2.307
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.10/? GLN 189 NE2  SarsCov2_structure19R_nsp5holo_rep1.pdb #1.10/A UNL 888 S  SarsCov2_structure19R_nsp5holo_rep1.pdb #1.10/? GLN 189 2HE2  3.693  2.786
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.11/A UNL 888 N    SarsCov2_structure19R_nsp5holo_rep1.pdb #1.11/? THR 190 O  SarsCov2_structure19R_nsp5holo_rep1.pdb #1.11/A UNL 888 H     3.159  2.268
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.12/? GLU 166 N    SarsCov2_structure19R_nsp5holo_rep1.pdb #1.12/A UNL 888 O  SarsCov2_structure19R_nsp5holo_rep1.pdb #1.12/? GLU 166 H     2.648  1.817
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.13/A UNL 888 N    SarsCov2_structure19R_nsp5holo_rep1.pdb #1.13/? THR 190 O  SarsCov2_structure19R_nsp5holo_rep1.pdb #1.13/A UNL 888 H     3.176  2.395
SarsCov2_structure19R_nsp5holo_rep1.pdb #1.14/A UNL 888 N    SarsCov2_structure19R_nsp5holo_rep1.pdb #1.14/? PHE 140 O  SarsCov2_structure19R_nsp5holo_rep1.pdb #1.14/A UNL 888 H     2.833  1.955

我需要打印与样本 (1-14) 相关联的数字,该数字应对应于两种模式的首次出现:“GLU 166 N”和“CYS 44 O”,没有其他模式同一样本内。我需要在与此模式关联的#1.number/? 模式之前的同一行上打印出现的数字。所以在这个例子中,检测到的数字应该是 3(因为关联数字是#1.3/?),其中可以找到两种模式(而不是其他模式!)。最后,如果找不到这两种模式,我想用第一个模式“GLU 166 N”打印对应于样本的数字(就像我的例子)

目前,我的 AWK 解决方案专注于一种基于模式的搜索:查找第一次出现的“GLU 166 N”(如果找不到模式,脚本会打印 1 )。基本上,它会在该行的任何位置查找“模式”,然后从第二个字段打印数字的第二部分(在点之后)":


awk -vn=1 '/GLU 166 N/ {gsub(/.*\.|\/\?/,"",); n=; exit} END {print n}' input.log

根据我们有意义的讨论,你能不能试试:

awk -F# '                               # split line on '#' into fields
{
    for (i = 1; i <= NF; i++) {         # loop over the fields
        if (match($i, /^1\.[0-9]+\/\? GLU 166 N/)) {
            sub(/^1\./, "", $i); sub(/\/.*/, "", $i)
                                        # extract the number after "1." in $i
            if (first == "") first = $i # keep the first found value as a fallback
            if ($i in b) {              # if the number exists also in b
                queue[++qn] = $i        # then push it in the queue
            }
            a[$i]
            next
        } else if (match($i, /^1\.[0-9]+\/\? CYS 44 O/)) {
            sub(/^1\./, "", $i); sub(/\/.*/, "", $i)
            if ($i in a) {
                queue[++qn] = $i
            }
            b[$i]
            next
        } else if (match($i, /^1\.[0-9]+\/\? [A-Z]{3} [0-9]+ [A-Z][A-Z0-9]*/)) {
                                        # analyse other patterns
            sub(/^1\./, "", $i); sub(/\/.*/, "", $i)
            exclude[$i]
        }
    }
}
END {
    for (i = 1; i <= qn; i++) {         # examine the queue in appearance order
        j = queue[i]                    # j is the matched number
        if (! (j in exclude)) {         # if not found in other patterns
            print j                     # then it is the answer
            exit
        }
    }
    if (first == "") print "1"          # the default value
    else print first                    # the fallback
}' input.log
  • 它搜索名称:GLU 166 NCYS 44 O和其他物质 以及嵌入在前导形式中的相关数字 #1.<num>/?.
  • 如果GLU 166 NCYS 44 O的号码相同,则号码为 按出现顺序推入 queue
  • 我们需要消除也与其他物质一起出现的数字 (除非它出现在同一行中的任何一个之后)。 数组 exclude 存储与这些物质相关的数字。
  • END 块中,我们按顺序检查 queue 中的数字。 队列中未包含在 exclude 中的第一个号码将是 用作答案。
  • 如果GLU 166 NCYS 44 O没有相同的数字,第一个 找到的带有 GLU 166 N 的数字用作后备。
  • 万一找不到模式,将使用 1

[编辑]
这是使用 bash 变量作为搜索模式并将 bash 变量 var 分配给输出的单行代码:

search_pattern1='GLU 166 N'
search_pattern2='CYS 44 O'

var=$(awk -F# -v pat1="$search_pattern1" -v pat2="$search_pattern2" '{for (i = 1; i <= NF; i++) {if (match($i, "^1\.[0-9]+\/\? "pat1)) {sub(/^1\./, "", $i); sub(/\/.*/, "", $i); if (first == "") first = $i; if ($i in b) {queue[++qn] = $i} a[$i]; next} else if (match($i, "^1\.[0-9]+\/\? "pat2)) {sub(/^1\./, "", $i); sub(/\/.*/, "", $i); if ($i in a) {queue[++qn] = $i} b[$i]; next} else if (match($i, /^1\.[0-9]+\/\? [A-Z]{3} [0-9]+ [A-Z][A-Z0-9]*/)) { sub(/^1\./, "", $i); sub(/\/.*/, "", $i); exclude[$i]}}} END {for (i = 1; i <= qn; i++) {j = queue[i]; if (! (j in exclude)) {print j; exit}} if (first == "") print "1"; else print first}' input.log)

[说明]
在 awk 中使用变量作为正则表达式模式时,我们需要注意 报价。在很多情况下我们会使用这样的语句:

if (match([=12=], /regex/)) ...

其中斜杠用作 quotes 来括起正则表达式模式。 引号内的裸词被视为 文字字符串 ,而不是变量 姓名。这就是为什么我们不能将变量名放在引号内。 例如,如果我们说:

if (match($i, /^1\.[0-9]+\/\? pat1/)) ...

单词pat1不再是变量名。这只是一个文字字符串。

如何解决?我们需要把带引号的字符串和变量 并排以便 awk 将它们连接成一个模式:

if (match($i, "^1\.[0-9]+\/\? "pat1)) ...
  • 在这种情况下,我们不能使用斜线引号。相反,我们需要 使用双引号。
  • 我们需要添加另一个反斜杠来转义 双引号。

顺便说一下,您的 post “我如何在我的 Awk 脚本中使用 bash 变量?”已 不幸的是,由于 duplicate 而被关闭。然而必不可少的 问题不存在。恐怕审稿人不明白 你想做什么。