无法用grep提取

时间:2016-10-23 05:31:01

标签: regex bash grep

> <img alt="Citizen Kane Poster" title="Citizen Kane Poster"
src="https://images-na.ssl-images-amazon.com/images/M/MV5BMTQ2Mjc1MDQwMl5BMl5BanBnXkFtZTcwNzUyOTUyMg@@._V1_UX182_CR0,0,182,268_AL_.jpg"
itemprop="image" />

我想从上面的文字中提取海报的网址。 这是我的grep声明:

count=$(grep -zPo '(?<=> <img alt=").*?src="\K.*?(?="itemprop="image")'  ~/movie_local)

movie_local是我保存网站页面源的地方。 我正在学习grep而且还没有完全掌握它,所以请对我软一点。请你帮帮我吧? :)

1 个答案:

答案 0 :(得分:2)

(如前所述,最好的解决方案是使用HTML解析器。)

使用 GNU grep,请尝试使用此简化版本:

grep -zPo '<img alt=[^/]+?src="\K[^"]+' ~/movie_local

原始尝试的固定版本(请注意(?s)前缀;请参阅下面的说明):

grep -zPo '(?s)> <img alt=".*?src="\K.*?(?=")' ~/movie_local

替代方案,[\s\S]使用ad-hoc匹配任何字符,包括\n

grep -zPo '> <img alt="[\s\S]*?src="\K.*?(?=")' ~/movie_local

至于为什么你的尝试不起作用

  • 当您使用-P (用于PCRE (Perl-Compatible Regular Expression支持)时, . 匹配{ {1}}字符。 默认 ,因此,即使您使用\n一次读取整个输入,-z也不会跨行边界匹配。你有两个选择:

    • 在正则表达式的开头设置option s ("dotall") - .* - 这会使(?s)匹配任何字符,包括{{ 1}}
    • 临时解决方法:使用. 而不是\n
  • 顺便说一句: [\s\S]构造在语法上比较简单,有时更灵活替代到一个外观断言({{ 1}}

    • 您的命令都是,在这种情况下没有任何损害,但是没有必要。
    • 相比之下,如果您尝试使用.进行更灵活的空白匹配 - 请注意\K代替原始单个空格 - 您的后瞻断言将失败,因为lookbehind断言必须是固定长度(至少从GNU (?<=...) v2.26开始)。
      但是,仅使用(?<=>\s*<img alt=")就可以了:\s* grep只删除与匹配的所有内容(不包括在输出中)。