【问题标题】:Manipulation of the text between two parents处理两个父母之间的文本
【发布时间】:2020-05-19 09:24:10
【问题描述】:

我有以下 html 文本,其中“tr”的数量是动态的:

<tr>
    <td>Dec 1, 2019 11:12 PM</td>
    <td>some text1</td>
    <td>some text2</td>
    <td>some text3</td>
    <td>
        <input type=button value="Add" id="add" onCLick="add(12345)" data-toggle="modal" data-target="#add" />
    </td>
    <td></td>
</tr>

<tr>
    <td>Dec 5, 2019 4:33 PM</td>
    <td>some text1</td>
    <td>some text2</td>
    <td>some text3</td>
    <td>
        <input type=button value="Add" id="add" onCLick="add(12345)" data-toggle="modal" data-target="#add" />
    </td>
    <td></td>
</tr>

<tr>
    <td>Dec 9, 2019 1:06 PM</td>
    <td>some text1</td>
    <td>some text2</td>
    <td>some text3</td>
    <td>
        <input type=button value="Add" id="add" onCLick="add(12345)" data-toggle="modal" data-target="#add" />
    </td>
    <td></td>
</tr>

我想得到以下结果:

Dec 1, 2019 11:12 PM | some text1 | some text2 | some text3 
Dec 5, 2019 4:33 PM | some text1 | some text2 | some text3 
Dec 9, 2019 1:06 PM | some text1 | some text2 | some text3 

我尝试使用 sed 进行分组:

sed '/^<tr>/d;:a;N;/^<\/tr>/M!s/\n/ /;ta;P;d'

但它当然不起作用。任何建议如何处理?

【问题讨论】:

  • 使用 HTML 解析器。
  • 使用 bash 解析 HTML 的坏主意

标签: html bash sed


【解决方案1】:

这可能对你有用(GNU sed):

sed -E '/<tr>/{:a;x;/\n/{s/<\/?t[rd]>/\n/g;s/^\s.*//mg;s/\n+/ | /g;s/^...|...$//g;p};x;h;d};//!H;$!d;ba' file

&lt;tr&gt;&lt;\tr&gt; 之间的行收集到保留空间中。如果在遇到&lt;tr&gt; 标记时保留空间已经包含行,则将集合操作为所需的格式:用换行符替换标记,删除以空格开头的行,用| 替换一个或多个换行符以及顶部和尾部前 3 个字符工件并打印制造记录。

【讨论】:

    【解决方案2】:

    如前所述,请使用 HTML 解析器,例如 xidel

    Xidel 是一个命令行工具,用于下载和提取数据 HTML/XML 页面以及 JSON-API,使用 CSS、XPath 3.0、XQuery 3.0、 JSONiq 或模式模板。它还可以创建新的或转换的 XML/HTML/JSON 文档。

    xidel -s input.html -e '//tr/join(td[position()<5]," | ")'
    Dec 1, 2019 11:12 PM | some text1 | some text2 | some text3
    Dec 5, 2019 4:33 PM | some text1 | some text2 | some text3
    Dec 9, 2019 1:06 PM | some text1 | some text2 | some text3
    

    在人类方面:对于每个 tr-node 选择前 4 个 td-nodes 的文本节点并将它们连接在一起,由 | 分隔。

    另见this xidelcgi demo

    【讨论】:

      【解决方案3】:

      除非你想要一个快速和肮脏的解决方案,否则解析 html 应该使用 html 解析器完成,如 cmets 中所说。

      例如使用python:

      import bs4 # bs4 stands for beautifulsoup, a html parser
      import csv
      
      # I open both input and output file
      with open(<input>) as myinput, open(<output>, "w") as myoutput:
          # I parse the html
          soup = bs4.BeautifulSoup(myinput, 'html.parser')
          # I set the delimiter for the csv
          csvwriter = csv.writer(myoutput, delimiter="|")
      
          # For each tr tag
          for tr in soup.find_all('tr'):
              # Here I create a list that contains all text from td
              rows = [td.text for td in tr.find_all('td')]
              # I write the 4th first values as a csv row
              csvwriter.writerow(rows[:4])
      

      现在,如果您不相信这个不错的解决方案,让我们看看使用 awk 的快速和肮脏的解决方案:

      awk '
         # I define here input and output delimiters
         BEGIN{FS="<|>"; OFS=" | "}
         # I store info in array td_info
         /<td>/{td_info[++counter]=$3} 
         # I print the info I need and clean td_info array and counter
         /<\/tr>/{
             print td_info[1], td_info[2], td_info[3], td_info[4]
             counter=0
             delete td_info
         }
      ' <input.html>
      

      输出:

      Dec 1, 2019 11:12 PM | some text1 | some text2 | some text3
      Dec 5, 2019 4:33 PM | some text1 | some text2 | some text3
      Dec 9, 2019 1:06 PM | some text1 | some text2 | some text3
      

      【讨论】:

        【解决方案4】:

        这是一种完全不同的方法 - 只是为了让您了解 XSLT。老实说,我通常不是 XSLT 的粉丝,坦率地说,它不适合您提供的 HTML 示例。其实这个问题不匹配,但是加入讨论就好了。

        首先,HTML 不是严格兼容 XML。但在这种情况下,有趣的是要注意我必须对您的输入做些什么以使其与 XML 兼容:

        1. 引用“按钮”。所以现在输入元素上的 type 属性被引用了:

        2. 我必须将所有元素包装在一个根元素中。我选择了

          ,但我几乎可以选择任何东西。

          这是一个 XSLT 方法:

          function xsl {
          cat  <<EOF
          <?xml version="1.0" encoding="UTF-8"?>
          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:mpd="urn:mpeg:dash:schema:mpd:2011" version="1.0">
            <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
            <xsl:param name="locale">en</xsl:param>
            <xsl:template match="//tr"><xsl:value-of select="td[1]"/> | <xsl:value-of select="td[2]"/> | <xsl:value-of select="td[3]"/> | <xsl:value-of select="td[4]"/></xsl:template>
          </xsl:stylesheet>
          EOF
          }
          
          xsltproc <( xsl ) -  <<EOF
          <table>
          <tr>
              <td>Dec 1, 2019 11:12 PM</td>
              <td>some text1</td>
              <td>some text2</td>
              <td>some text3</td>
              <td>
                  <input type="button" value="Add" id="add" onCLick="add(12345)" data-toggle="modal" data-target="#add" />
              </td>
              <td></td>
          </tr>
          
          <tr>
              <td>Dec 5, 2019 4:33 PM</td>
              <td>some text1</td>
              <td>some text2</td>
              <td>some text3</td>
              <td>
                  <input type="button" value="Add" id="add" onCLick="add(12345)" data-toggle="modal" data-target="#add" />
              </td>
              <td></td>
          </tr>
          
          <tr>
              <td>Dec 9, 2019 1:06 PM</td>
              <td>some text1</td>
              <td>some text2</td>
              <td>some text3</td>
              <td>
                  <input type="button" value="Add" id="add" onCLick="add(12345)" data-toggle="modal" data-target="#add" />
              </td>
              <td></td>
          </tr>
          </table>
          EOF
          

          这是 MAC 上的输出:

          Dec 1, 2019 11:12 PM | some text1 | some text2 | some text3
          
          Dec 5, 2019 4:33 PM | some text1 | some text2 | some text3
          
          Dec 9, 2019 1:06 PM | some text1 | some text2 | some text3
          

          【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-02-18
          • 2015-01-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-05-14
          相关资源
          最近更新 更多