【问题标题】:Extract Text between HTML tags with sed or grep使用 sed 或 grep 提取 HTML 标记之间的文本
【发布时间】:2017-12-13 04:40:20
【问题描述】:

我有一个问题。我想使用 sed 或 grep 命令在值中获取此 html 的两个部分。我怎样才能把它们都提取出来?

test.html:

<html>
 <body>
  <div id="foo" class="foo">
   Some Text.
    <p id="author" class="author">
     <br>
     <a href="example.com">bar</a>
    </p>
  </div>
 </body>
</html>

脚本.sh

#!/bin/bash

author=$(sed 's/.*<p id="author" class="author"><br><a href="*">\(.*\)<\/a><\/p>.*/\1/p' test.html)
quote=$(sed 's/.*<div id="foo" class="foo">\(.*\)<\/div>.*/\1/p' test.html)

在该行下,我只想要值中的文本。没有html标签。 但是我的脚本不起作用..

【问题讨论】:

  • 使用像stackoverflow.com/tags/xmlstarlet/info这样的html解析器而不是正则表达式
  • $author 和 $quote 应该包含什么?
  • 我无法使用 xmlstarlet。我没有 sudo 访问权限。
  • @Cyrus author -> "bar" and quote -> "Some Text."

标签: html bash sed grep


【解决方案1】:

don't use regex to parse HTML/XML,但请改用 之类的专用解析器:

$ xidel -s test.html -e '//p/a,//div/normalize-space(text())'
bar
Some Text.
$ eval $(xidel test.html -se 'author:=//p/a,quote:=//div/normalize-space(text())' --output-format=bash)

$ printf '%s\n' "$author" "$quote"
bar
Some Text.

【讨论】:

    【解决方案2】:

    您可以使用html2text

    # cat test.html | html2text
    Some Text.
    
    
    [bar](example.com)
    

    我经常使用 curl

    # curl -s http://www.example.com/ | html2text
    
    # Example Domain
    
    This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.
    
    [More information...](https://www.iana.org/domains/example)
    
    #
    

    【讨论】:

      【解决方案3】:

      您可以使用xmllint 解析 html/xml 文本并提取已定义 xpath 的值。

      下面是工作示例:

      #!/bin/bash
      
      author=$(xmllint --html --xpath '//div[@class="foo"]/text()' test.html | tr -d '\n' | sed -e "s/ //g")
      quote=$(xmllint --html --xpath '//a/text()' test.html | sed -e "s/ //g")
      echo "Author:'$author'"
      echo "Quote:'$quote'"
      
      • xpath 定义需要从中提取文本的 xml 节点路径。
      • tr 用于删除换行符。
      • sed 用于从提取的文本值中修剪字符串。

      【讨论】:

        【解决方案4】:

        代码:

        text="$(sed 's:^ *::g' < test.html | tr -d \\n)"
        author=$(sed 's:.*<p id="author" class="author"><br><a href="[^"]*">\([^<]*\)<.*:\1:' <<<"$text")
        quote=$(sed 's:.*<div id="foo" class="foo">\([^<]*\)<.*:\1:' <<<"$text")
        echo "'$author' '$quote'"
        

        工作原理:

        1. $text 被分配了test.html 的未缩进单行表示;请注意: 用作sed 的分隔符而不是/,因为任何字符都可以作为分隔符,并且我们正在解析的文本存在/-s,所以我们没有在构造正则表达式时使用\-s 转义它们。
        2. $author 假定在&lt;p id="author" class="author"&gt;&lt;br&gt;&lt;a href="[^"]*"&gt; 之间(其中[^"]* 表示«除" 之外的任何字符,重复N 次,N ∈ [0, +∞)»)和接下来出现的任何标签。
        3. $quote 假定在 &lt;div id="foo" class="foo"&gt; 和接下来的任何标签之间。
        4. 比较晦涩的构造&lt;&lt;&lt;"$text"就是所谓的here-string,几乎相当于放在开头的echo "$text" |

        【讨论】:

        • 引用部分不起作用。它返回完整的字符串
        • @mete 或从您的问题中尝试test.html。它确实有效:ideone.com/9pPZoZ
        猜你喜欢
        • 2012-10-20
        • 2014-11-13
        • 1970-01-01
        • 2013-09-09
        • 2012-10-25
        • 1970-01-01
        • 2014-10-03
        • 2017-05-06
        • 1970-01-01
        相关资源
        最近更新 更多