在模式之间每四行添加两行 - SED

时间:2012-08-28 12:32:27

标签: sed

我需要Sed的一些帮助。我在Windows和Mac OSX上使用它。我需要在Sed中添加一个

</tr>
<tr>

在发现第一个<tr>后的每4行,并在</tr>上停止执行

我找不到办法做到这一点。 每个文件最多有20个表,所以我需要自动执行...

从此更改

<div class="titulo"> TERMINAL CAPAO DA IMBUIA</div>
<div class="dataedia">
Válido a partir de: 30/07/2012 - 
DIA ÚTIL</div>
<table>
<tr>
<td>05:50</td>
<td>05:58</td>
<td>06:04</td>
<td>06:08</td>
<td>06:12</td>
<td>06:15</td>
<td>06:17</td>
<td>06:20</td>
<td>06:22</td>
<td>06:25</td>
<td>06:27</td>
<td>06:30</td>
<td>06:32</td>
<td>06:35</td>
<td>06:37</td>
<td>06:39</td>
<td>06:42</td>
<td>06:44</td>
<td>06:47</td>
<td>06:49</td>
<td>06:52</td>
<td>06:54</td>
<td>06:57</td>
<td>06:59</td>
<td>07:01</td>
<td>07:04</td>
<td>07:06</td>
<td>07:09</td>
<td>07:11</td>
<td>07:14</td>
<td>07:16</td>
<td>07:18</td>
<td>07:21</td>
<td>07:23</td>
<td>07:26</td>
<td>07:28</td>
<td>07:31</td>
<td>07:33</td>
<td>07:36</td>
<td>07:38</td>
</tr>
</table>
</div>

到这个

<div class="titulo"> TERMINAL CAPAO DA IMBUIA</div>
<div class="dataedia">
Válido a partir de: 30/07/2012 - 
DIA ÚTIL</div>
<table>
<tr>
<td>05:50</td>
<td>05:58</td>
<td>06:04</td>
<td>06:08</td>
</tr>
<tr>
<td>06:12</td>
<td>06:15</td>
<td>06:17</td>
<td>06:20</td>
</tr>
<tr>
<td>06:22</td>
<td>06:25</td>
<td>06:27</td>
<td>06:30</td>
</tr>
<tr>
<td>06:32</td>
<td>06:35</td>
<td>06:37</td>
<td>06:39</td>
</tr>
<tr>
<td>06:42</td>
<td>06:44</td>
<td>06:47</td>
<td>06:49</td>
</tr>
<tr>
<td>06:52</td>
<td>06:54</td>
<td>06:57</td>
<td>06:59</td>
</tr>
<tr>
<td>07:01</td>
<td>07:04</td>
<td>07:06</td>
<td>07:09</td>
</tr>
<tr>
<td>07:11</td>
<td>07:14</td>
<td>07:16</td>
<td>07:18</td>
</tr>
<tr>
<td>07:21</td>
<td>07:23</td>
<td>07:26</td>
<td>07:28</td>
</tr>
<tr>
<td>07:31</td>
<td>07:33</td>
<td>07:36</td>
<td>07:38</td>
</tr>
</table>
</div>

是否可以使用sed?如果没有,我应该使用什么工具?

由于

6 个答案:

答案 0 :(得分:3)

我不喜欢使用sed来处理HTML代码的想法。说,试试这个:

script.sed的内容:

## For every line between '<tr>' and '</tr>' do ...
/<tr>/,/<\/tr>/ {

    ## Omit range edges.
    /<\/\?tr>/ b;

    ## Append '<td>...</td>' to Hold Space (HS).
    H;  

    ## Get HS to Pattern Space (PS) to work with it.
    x;  

    ## If there are at least four newline characters means that exists four
    ## '<td>' tags too, so add a '<tr>' before them and a '</tr>' after them,
    ## print, and delete them (already processed).
    /\(\n[^\n]*\)\{4\}/ {
        s/^\(\n\)/<tr>\1/;
        s/$/\n<\/tr>/;
        p   
        s/^.*$//;
    }   

    ## Save the '<td>'s to HS again and read next line.
    x;  
    b;  
}

## Print all lines out of the range.
p;

假设infile在问题中发布了数据,请运行以下脚本:

sed -nf script.sed infile

产量:

<div class="titulo"> TERMINAL CAPAO DA IMBUIA</div>
<div class="dataedia">
Válido a partir de: 30/07/2012 - 
DIA ÚTIL</div>
<table>
<tr>
<td>05:50</td>
<td>05:58</td>
<td>06:04</td>
<td>06:08</td>
</tr>
<tr>
<td>06:12</td>
<td>06:15</td>
<td>06:17</td>
<td>06:20</td>
</tr>
<tr>
<td>06:22</td>
<td>06:25</td>
<td>06:27</td>
<td>06:30</td>
</tr>
<tr>
<td>06:32</td>
<td>06:35</td>
<td>06:37</td>
<td>06:39</td>
</tr>
<tr>
<td>06:42</td>
<td>06:44</td>
<td>06:47</td>
<td>06:49</td>
</tr>
<tr>
<td>06:52</td>
<td>06:54</td>
<td>06:57</td>
<td>06:59</td>
</tr>
<tr>
<td>07:01</td>
<td>07:04</td>
<td>07:06</td>
<td>07:09</td>
</tr>
<tr>
<td>07:11</td>
<td>07:14</td>
<td>07:16</td>
<td>07:18</td>
</tr>
<tr>
<td>07:21</td>
<td>07:23</td>
<td>07:26</td>
<td>07:28</td>
</tr>
<tr>
<td>07:31</td>
<td>07:33</td>
<td>07:36</td>
<td>07:38</td>
</tr>
</table>
</div>

答案 1 :(得分:1)

尝试awk

awk '{print}; /<td>/ && ++i==4 {print "</tr>\n<tr>"; i=0}' file
  • 打印行
  • 如果是<td>,则增加i
  • 如果i 4打印</tr><tr>并重置i

使用给定输入测试返回所需的输出, 唯一的“问题”是在列表末尾出现额外的<tr></tr>。 这是可以解决的,但我的时间不多了。 当我回来时,如果您认为需要,我可以调查一下。

...结果文件末尾的一部分

<td>07:26</td>
<td>07:28</td>
</tr>
<tr>
<td>07:31</td>
<td>07:33</td>
<td>07:36</td>
<td>07:38</td>
</tr>
<tr>             <-- extra <tr></tr> here
</tr>
</table>

答案 2 :(得分:1)

你可以试试正则表达式。您可以测试以下表达式: http://gskinner.com/RegExr/

Catch表达式:

?</td>.<td>.*?</td>.<td>.*?</td>.<td>.*?</td>)(?!.</tr>)

替换表达式:

$1\n</tr>\n<tr>

检查标志:

global, ignorecase, dotall

结果:

<table>
<tr>
<td>05:50</td>
<td>05:58</td>
<td>06:04</td>
<td>06:08</td>
</tr>
<tr>
<td>06:12</td>
<td>06:15</td>
<td>06:17</td>
<td>06:20</td>
</tr>
<tr>
<td>06:22</td>
<td>06:25</td>
<td>06:27</td>
<td>06:30</td>
</tr>
<tr>
<td>06:32</td>
<td>06:35</td>
<td>06:37</td>
<td>06:39</td>
</tr>
<tr>
<td>06:42</td>
<td>06:44</td>
<td>06:47</td>
<td>06:49</td>
</tr>
<tr>
<td>06:52</td>
<td>06:54</td>
<td>06:57</td>
<td>06:59</td>
</tr>
<tr>
<td>07:01</td>
<td>07:04</td>
<td>07:06</td>
<td>07:09</td>
</tr>
<tr>
<td>07:11</td>
<td>07:14</td>
<td>07:16</td>
<td>07:18</td>
</tr>
<tr>
<td>07:21</td>
<td>07:23</td>
<td>07:26</td>
<td>07:28</td>
</tr>
<tr>
<td>07:31</td>
<td>07:33</td>
<td>07:36</td>
<td>07:38</td>
</tr>
</table>
</div>

您可以使用Notepad ++等编辑器同时批量替换许多文件(语法会略有不同)。

答案 3 :(得分:1)

Perl解决方案,仍然使用正则表达式而不是解析HTML:

perl -pe '
    undef $inside if m{</tr>};
    if ($inside and ($. % 4) == $tr_line) {
        print "</tr>\n<tr>\n";
    }
    $inside = 1 if defined $tr_line;
    $tr_line = ($. + 1) % 4 if /<tr>/;
    ' file

答案 4 :(得分:1)

sed '\!<td>!,\!</table!{N;N;N;i\
</tr>\
<tr>
}' input_file

答案 5 :(得分:0)

使用xsh

open :F html file ;                                                   # Open as html.
while //table/tr[count(td)>4] wrap :U position()=8 tr //table/tr/td ; # Wrap four td's into a tr.
xmove :r //table/tr/tr before .. ;                                    # Unwrap the extra tr.
remove //table/tr[last()] ;                                           # Remove the extra tr.