3

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

</tr>
<tr>

每4行,第一次<tr>找到后,就停止做</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吗?如果没有,我应该使用什么工具?

谢谢

4

6 回答 6

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>
于 2012-08-28T12:54:20.893 回答
1

尝试awk

awk '{print}; /<td>/ && ++i==4 {print "</tr>\n<tr>"; i=0}' file
  • 打印行
  • 如果是<td>则增加i
  • 如果i4打印</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>
于 2012-08-28T12:49:03.200 回答
1

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

捕捉表达式:

?</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++ 之类的编辑器一次对多个文件进行批量替换(语法会略有不同)。

于 2012-08-28T12:58:34.803 回答
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
于 2012-08-28T13:04:50.240 回答
1
sed '\!<td>!,\!</table!{N;N;N;i\
</tr>\
<tr>
}' input_file
于 2012-08-28T13:14:56.600 回答
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.
于 2012-08-28T21:58:23.473 回答