使用 sed 合并行组

使用 sed 合并行组

我想合并文件中的每一组行:

    <tr>
            <td >441</td>
            <td >S</td>
            <td >0,74</td>
    </tr>
    <tr>
            <td >442</td>
            <td >S</td>
            <td >0,14</td>
    </tr>

到一行(td 之间的空格或制表符的数量对我来说并不重要):

    <tr> <td >441</td> <td >S</td> <td >0,74</td> </tr>
    <tr> <td >442</td> <td >S</td> <td >0,14</td> </tr>

每个组(在 vi 中使用 ':set line')如下所示:

     ^I<tr>$
     ^I^I<td >441</td>$
     ^I^I<td >S</td>$
     ^I^I<td >0,74</td>$
     ^I</tr>$

我自己使用 sed 命令做这件事确实遇到了问题。任何帮助都将不胜感激。

答案1

这是一个使用 perl 而不是 sed 的解决方案。我发现这个解决方案更易于阅读和理解。

perl -pe 's|\n|| ; s|</tr>|</tr>\n|' file

输出:

<tr>    <td >441</td>   <td >S</td>     <td >0,74</td></tr>
<tr>    <td >442</td>   <td >S</td>     <td >0,14</td></tr>

答案2

使用 sed,您可以执行以下操作:

$ cat inf
    <tr>
            <td >441</td>
            <td >S</td>
            <td >0,74</td>
    </tr>
$ sed ':a;N;s/\n//;ta' inf
    <tr>            <td >441</td>           <td >S</td>         <td >0,74</td>  </tr>

这样做的目的是:

  • :a做标签
  • N会将当前行附加到缓冲区,从而允许下一个命令
  • s/\n//将用空值替换上一个命令中的新行,从而有效地连接行
  • ta是“转到:a”

更简单的方法是使用tr

$ cat inf
    <tr>
            <td >441</td>
            <td >S</td>
            <td >0,74</td>
    </tr>
$ cat inf|tr -d '\n'
    <tr>            <td >441</td>           <td >S</td>         <td >0,74</td>  </tr>

意思-d '\n'是“删除新行”。

编辑:误解了你想要什么。如果你想在一个输入流中处理上述多个组,你可以这样做sed

$ cat inf
  foo
  baz
    <tr>
            <td >441</td>
            <td >S</td>
            <td >0,74</td>
    </tr>
  fizz
  buzz
    <tr>
            <td >441</td>
            <td >S</td>
            <td >0,74</td>
    </tr>
  tomato
  potato
$ sed -r '/<tr/{:a;N;s/[\t\n]//g;/<\/tr/!ba}' inf
  foo
  baz
<tr><td >441</td><td >S</td><td >0,74</td></tr>
  fizz
  buzz
<tr><td >441</td><td >S</td><td >0,74</td></tr>
  tomato
  potato

awk正如其他人提到的,你可以用或或python以更易读的形式执行此操作perl,但请注意一件事 - regexp 不够强大,无法解析 HTML 或 XML。请参阅此文以获得更好的讨论:

希望这可以帮助。

答案3

# cat foo.html | xargs echo -n
<tr> <td >441</td> <td >S</td> <td >0,74</td> </tr>

或者删除所有空格......

# cat foo.html | xargs -n1 echo -n
<tr><td>441</td><td>S</td><td>0,74</td></tr>

你可以通过以下方式从 vi 内部实现这种效果:

!!xargs echo -n

答案4

sed -r ':k /<tr>/,/<\/tr>/{/<\/tr>/! {N;s/\n/ /;tk}}' file

$ cat file
    <tr>
        <td >441</td>
        <td >S</td>
        <td >0,74</td>
    </tr>
    <tr>
        <td >442</td>
        <td >S</td>
        <td >0,14</td>
    </tr>

$ sed -r ':k /<tr>/,/<\/tr>/{/<\/tr>/! {N;s/\n/ /;tk}}' file
    <tr>    <td >441</td>   <td >S</td>     <td >0,74</td> </tr>
    <tr>    <td >442</td>   <td >S</td>     <td >0,14</td> </tr>

相关内容