【问题标题】:Simple Grep Mismatch problem简单的 Grep 不匹配问题
【发布时间】:2011-10-02 09:09:49
【问题描述】:

我正在使用 Ubuntu 10.10 并使用 Grep 处理一些 HTML 文件。

这里是 HTML sn-p:

<a href="video.php?video=one-hd.mov"><img src="/1.jpg"><a href="video.php?video=normal.mov"><img src="/2.jpg"><a href="video.php?video=another-hd.mov">

我想提取one-hd.movanother-hd.mov 但忽略normal.mov

这是我的代码:

example='<a href="video.php?video=one-hd.mov"><img src="/1.jpg"><a href="video.php?video=normal.mov"><img src="/2.jpg"><a href="video.php?video=another-hd.mov">'
echo $example | grep -Po '(?<=video.php\?video=).*?(?=-hd.mov">)'

结果是:

one
normal.mov"><img src="/2.jpg"><a href="video.php?video=another

但我想要

one
another

那里不匹配。

是不是因为所谓的Greedy正则表达式?

我正在使用 GREP,但欢迎使用任何命令行 bash 工具来解决此问题,例如 sed 等。

非常感谢。

【问题讨论】:

  • 按照通常的答案,永远不要尝试将 HTML 与正则表达式匹配:stackoverflow.com/questions/1732348/…
  • @Marc B 那么我应该使用什么来处理 HTML。实际上 Grep if gr8 用于 HTML 处理。
  • Grep 非常适合查找东西。但唯一能正确处理 HTML 的是 DOM 解析器。其他任何东西都会在某个时候转身咬你。

标签: regex linux bash command-line grep


【解决方案1】:

您想对 grep 使用 Perl 正则表达式 - 为什么不直接使用 perl?

echo "$example" | perl -nle 'm/.*?video.php\?video=([^"]+)">.*video.php\?video=([^"]+)".*/; print "=$1=$2="'

将打印

=one-hd.mov=another-hd.mov=

【讨论】:

  • 我知道。秘密是[^"]。以下也适用:echo $example | grep -Po '(?&lt;=video.php\?video=)([^"]+)(?=-hd.mov"&gt;)'
【解决方案2】:

这是一个使用 xmlstarlet 的解决方案:

$ example='<a href="video.php?video=one-hd.mov"><img src="/1.jpg"><a href="video.php?video=normal.mov"><img src="/2.jpg"><a href="video.php?video=another-hd.mov">'
$ echo $example | xmlstarlet fo -R 2>/dev/null | xmlstarlet sel -t -m "//*[substring(@href, string-length(@href) - 6, 7) = '-hd.mov']" -v 'substring(@href,17, string-length(@href) - 17 - 3)' -n
one-hd
another-hd

$

【讨论】:

  • 你还要数个字符?substring(@href,17, string-length(@href) - 17 - 3)?不如grep方便。
  • @DocWiki:但它更安全。您当然可以用 string-length() 函数和静态值替换数字,或者检查 xmlstarlet 支持的其他字符串函数。这只是一个关于如何使用它的例子。您还可以将 xmlstarlet 和 grep 结合使用,使用 xmlstarlet 仅提取 href 属性并使用 grep 获取您想要的文件名,如果您觉得更舒服的话。
【解决方案3】:

使用 awk 的解决方案:

{
    for(i=1;i<NF;i++) {
        if ($i ~ /mov/) {
            if ($i !~ /normal/){
                sub(/^.*=/, "", $i)
                print $i
            }
        }
    }
}

输出:

$ awk -F'"' -f h.awk html
one-hd.mov
another-hd.mov

但我强烈建议您为此使用 html 解析器,例如 BeautifulSoup

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 2018-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多