3

Я хотел бы объединить каждую группу строк из файла:

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

до одной строки (для меня не важно количество пробелов или табуляций между тд):

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

Каждая группа (с ':set line' в vi) выглядит так:

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

У меня есть реальная проблема сделать это самостоятельно с помощью команды sed. Любая помощь будет оценена.

6 ответов6

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 есть "гото: а"

Более простой способ - использовать 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 perl или python, но обратите внимание на одну вещь: регулярное выражение недостаточно мощно для анализа HTML или XML. Смотрите это для хорошего обсуждения:

Надеюсь это поможет.

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>
1

Решение с помощью :

awk '/<tr>/,/<\/tr>/{printf("%s", $0)};/<\/tr/{printf("\n")}' 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>

$  awk '/<tr>/,/<\/tr>/{printf("%s", $0)};/<\/tr/{printf("\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>
1
# 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
0
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>
0

если вы уверены в длине групп и по-прежнему хотите использовать sed , вы можете рассмотреть следующие варианты:

sed -e 'N;N;N;N;s/\(.*\)\n\(.*\)\n\(.*\)\n\(.*\)\n\(.*\)/\1\2\3\4\5/'

обратите внимание, как это решение позволяет вам отбрасывать или переставлять строки, но, как уже было сказано, оно зависит от согласованной длины групп во входном файле.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .