Удалите все строки между двумя шаблонами (исключая шаблон), используя sed или awk - PullRequest
10 голосов
/ 14 января 2012

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

Файлы выглядят расплывчато, как на следующем выходе.

 TEST #1          
      coef1 |   48.36895    3.32013    14.57   0.000     41.86141    54.87649
      coef2 |  -50.08894   10.47335    -4.78   0.000    -70.61697   -29.56092
            |
  indicator |
         0  |   .6647992   2.646627     0.25   0.802     -4.55925    5.888849
         1  |   2.118701   5.225777     0.41   0.686     -8.19621    12.43361
            |
       year |
         2  |  -.4324005   2.231387    -0.19   0.847    -4.836829    3.972028
         3  |   -.362762    1.97184    -0.18   0.854    -4.254882    3.529358
            |
      _cons |   16.95753   6.342342     2.67   0.008     4.526383    29.38869
 TEST #2          
        coef2 |   48.36895    3.32013    14.57   0.000     41.86141    54.87649
        coef3 |  -50.08894   10.47335    -4.78   0.000    -70.61697   -29.56092
              |
         year |
           4  |   .6647992   2.646627     0.25   0.802     -4.55925    5.888849
           5  |   2.118701   5.225777     0.41   0.686     -8.19621    12.43361
              |
     idnumber |
           6  |  -.4324005   2.231387    -0.19   0.847    -4.836829    3.972028
           7  |   -.362762    1.97184    -0.18   0.854    -4.254882    3.529358
              |
        _cons |   16.95753   6.342342     2.67   0.008     4.526383    29.38869

Мне нужно взять следующий вывод и удалить все строки между "year" и "_cons", но мне нужно сохранить строку, начинающуюся с "_cons".Требуемый вывод выглядит так:

 TEST #1          
      coef1 |   48.36895    3.32013    14.57   0.000     41.86141    54.87649
      coef2 |  -50.08894   10.47335    -4.78   0.000    -70.61697   -29.56092
            |
  indicator |
         0  |   .6647992   2.646627     0.25   0.802     -4.55925    5.888849
         1  |   2.118701   5.225777     0.41   0.686     -8.19621    12.43361
            |
       year |
      _cons |   16.95753   6.342342     2.67   0.008     4.526383    29.38869
 TEST #2          
        coef2 |   48.36895    3.32013    14.57   0.000     41.86141    54.87649
        coef3 |  -50.08894   10.47335    -4.78   0.000    -70.61697   -29.56092
              |
         year |
        _cons |   16.95753   6.342342     2.67   0.008     4.526383    29.38869

Я написал следующий скрипт (под OS X):

sed '/^ +year/,/^ +_cons/{/^ +year/!{/^ +_cons/!d}}' input.txt >output.txt

, но получил следующую ошибку:

sed: 1: "/^ +year/,/^ +_cons/{/^ ...": extra characters at the end of d command

Я не уверен, является ли этот подход правильным, потому что я не могу заставить его выполнить.Является ли sed здесь уместным, или я должен использовать awk?

Последнее замечание, мне нужен этот скрипт для работы с относительно общей установкой Unix.Я должен отправить это кому-то, кто должен выполнить его при очень простой установке AIX (я думаю).Нет Perl, нет Python, и я не могу много проблем с их установкой по электронной почте.

Ответы [ 5 ]

6 голосов
/ 14 января 2012

Это должно работать -

awk '/year/{print; getline; while($0!~/_cons/) {getline}}1' INPUT_FILE

или

awk '/_cons/{print;f=0;next}/year/{f=1;print;next}f{next}1' INPUT_FILE

Ниже приводится вывод с вашим файлом входных данных:

[jaypal:~/Temp] awk '/year/{print; getline; while($0!~/_cons/) {getline}}1' file
TEST #1          
      coef1 |   48.36895    3.32013    14.57   0.000     41.86141    54.87649
      coef2 |  -50.08894   10.47335    -4.78   0.000    -70.61697   -29.56092
            |
  indicator |
         0  |   .6647992   2.646627     0.25   0.802     -4.55925    5.888849
         1  |   2.118701   5.225777     0.41   0.686     -8.19621    12.43361
            |
       year |
      _cons |   16.95753   6.342342     2.67   0.008     4.526383    29.38869
 TEST #2          
        coef2 |   48.36895    3.32013    14.57   0.000     41.86141    54.87649
        coef3 |  -50.08894   10.47335    -4.78   0.000    -70.61697   -29.56092
              |
         year |
        _cons |   16.95753   6.342342     2.67   0.008     4.526383    29.38869

Test2:

[jaypal:~/Temp] awk '/_cons/{print;f=0;next}/year/{f=1;print;next}f{next}1' file
TEST #1          
      coef1 |   48.36895    3.32013    14.57   0.000     41.86141    54.87649
      coef2 |  -50.08894   10.47335    -4.78   0.000    -70.61697   -29.56092
            |
  indicator |
         0  |   .6647992   2.646627     0.25   0.802     -4.55925    5.888849
         1  |   2.118701   5.225777     0.41   0.686     -8.19621    12.43361
            |
       year |
      _cons |   16.95753   6.342342     2.67   0.008     4.526383    29.38869
TEST #2          
      coef2 |   48.36895    3.32013    14.57   0.000     41.86141    54.87649
      coef3 |  -50.08894   10.47335    -4.78   0.000    -70.61697   -29.56092
            |
       year |
      _cons |   16.95753   6.342342     2.67   0.008     4.526383    29.38869
3 голосов
/ 14 января 2012

Попробуйте добавить точку с запятой после d, чтобы указать, что команда завершилась.(GNU sed - единственный sed, с которым мне удобно тестировать - не требует этого, но, возможно, другой sed будет?)

Кроме того, если вам нужно поддерживать несколько реализаций sed, тогда вы не можете использовать + для обозначения «один или несколько»: это не стандарт, и не все реализации поддерживают его.Вы можете использовать \{1,\}, но это довольно уродливо.,,Я бы просто использовал * и добавил дополнительную копию.

Итак:

sed '/^ * year/,/^ * _cons/{/^ * year/!{/^ * _cons/!d;}}' input.txt >output.txt

(Протестировано, но только с использованием GNU sed, а не OS X, и, конечно, нетAIX, извините.)

2 голосов
/ 14 января 2012

Это может работать для вас:

 sed '/year/,/_cons/{//!d}' file

или

 awk '/_cons/{p=0};!p;/year/{p=1}' file
1 голос
/ 14 января 2012

Вы можете сделать это визуально. Просто откройте файл с помощью gVim и выполните команду:

:g/^\s*year/+1,/^\s*_cons/-1 d

Пояснение:

  • g глобальная команда
  • /^\s*year/+1 линия соответствия ниже year
  • /^\s*_cons/-1 строка соответствия выше _cons
  • d удалить диапазон
0 голосов
/ 28 июня 2017

Суммируя и обобщая два работающих решения GNU sed:

sed '/BEGIN/,/END/{/BEGIN/!{/END/!d;}}' input.txt
sed '/BEGIN/,/END/{//!d}' input.txt
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...