尝试使用 awk 在文件中查找两个字符串的匹配项

Trying to find a match of two strings in a file using awk

你好,我正在尝试使用 AWK 在一些 HTML 文件上找到模式匹配,但我似乎没有任何运气

所以要匹配我的模式,它应该具有以下内容

<tr>
                    <td>Failures</td>
                    <td>0</td>
                </tr>
                <tr>
                    <td>Warnings</td>
                    <td>4</td>
                </tr>
                <tr>
                    <td>Errors</td>
                    <td>0</td>
                </tr>
                <tr>
                    <td>Not Applicable</td>
                    <td>53</td>
                </tr>
                <tr>
                    <td>Manual Checks</td>
                    <td>9</td>
                </tr>

故障和手动检查应为零。所以在上面的文件中失败是0,手动检查是9。所以我只需要在失败是0,手动检查是0时匹配。

所以我尝试了转义和不转义新行,但是 awk 没有返回任何结果。

find . -name "*.html" -exec awk '/td\>Failures\<\/td\>\n.*\<td\>0/ {print FILENAME}' '{}' \;

我也试过像下面这样的其他组合,但似乎无法弄清楚为什么 awk 不会转到下一行。

find . -name "*.html" -exec awk '/td\>Failures\<\/td\>\n\[\^\\<\]\+\<td\>0/ {print FILENAME}' '{}' \;

任何人都可以看看并告诉我我缺少什么吗?

更可靠的解决方案将基于旨在解析 html 的工具;话虽如此...

一个 awk 使用几个自定义正则表达式模式的想法:

$ cat regex.awk
BEGIN { RS="^$"                                                 # whole file treated as a single line of input
        regex1="<td>Manual Checks</td>[[:space:]]+<td>0</td>"
        regex2="<td>Failures</td>[[:space:]]+<td>0</td>"
      }
[=10=] ~ regex1 && [=10=] ~ regex2 {print FILENAME}

注意: 将代码放在文件中 (regex.awk) 将使 follow-on find/awk 更清晰一些

示例输入:

$ cat f1.html
... snip ...
                    <td>Failures</td>
                    <td>0</td>                         # match
... snip ...
                    <td>Manual Checks</td>
                    <td>9</td>                         # not a match
... snip ...

$ cat f2.html
... snip ...
                    <td>Failures</td>
                    <td>0</td>                         # match
... snip ...
                    <td>Manual Checks</td>
                    <td>0</td>                         # match
... snip ...

注意: 添加注释以进行说明;注释在实际文件中不存在

将此添加到 find 调用:

$ find . -name "f?.html" -exec awk -f regex.awk '{}' \;                                                              
./f2.html

如果您的 html 文件是 well-formed xml,那么 将起作用:

find . -name '*.html' \
       -exec xmlstarlet sel -t \
               --if '//tr[td[1] = "Failures" and td[2] = "0"]' \
               --if '//tr[td[1] = "Manual Checks" and td[2] = "0"]' \
               --inp-name --nl \
             '{}' \;
  • 如果有一行的第一个单元格是 Failures 而第二个单元格是 0,
  • 如果有一行的第一个单元格是手动检查,第二个单元格是 0,
  • 然后打印输入的文件名和换行符。

在每个 Unix 机器上的任何 shell 中使用任何 awk:

$ cat tst.awk
gsub("^[[:space:]]*<td>|</td>[[:space:]]*$","") {
    if ( ++cnt % 2 ) {
        tag = [=10=]
    }
    else {
        f[tag] = [=10=]+0
    }
}
END {
    if ( (f["Failures"] == 0) && (f["Manual Checks"] == 0) ) {
        print FILENAME
    }
}

$ awk -f tst.awk file

上面创建了一个数组 f[],它将单元格的标签(名称)映射到它们的值,这样在 END 部分中,您可以对它们的任何组合进行任何测试。