Удалите все строки между двумя шаблонами (исключая шаблон) с помощью sed или awk
У меня есть несколько большой выходной текстовый файл, где мне нужно удалить все строки между двумя шаблонами, но сохранить соответствие шаблону.
Файлы выглядят нечетко похожими на следующий вывод.
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
Я написал следующий script (под 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 выполнить. Является ли sed даже подходящим здесь или я должен использовать awk?
Последнее замечание, мне нужно, чтобы этот script работал над относительно общей установкой Unix. Я должен отправить это кому-то, кто должен выполнить его по очень простой установке AIX (я думаю). Нет perl, нет python, и я не могу много разбираться в их установке по электронной почте.
Ответы
Ответ 1
Попробуйте добавить точку с запятой после d
, чтобы указать, что команда завершена. (GNU sed
— только sed
, который мне удобен для тестирования с помощью — не требует этого, но может быть, другой sed
будет?)
Кроме того, если вам нужно поддерживать несколько реализаций sed
, то вы не можете использовать +
для обозначения "один или несколько": он не является стандартным, и не все его реализации поддерживают его. Вы можете использовать \{1,\}
, но это довольно уродливо., Я бы просто использовал *
и наложил дополнительную копию.
Итак:
sed '/^ * year/,/^ * _cons/{/^ * year/!{/^ * _cons/!d;}}' input.txt >output.txt
(Протестировано, но только с использованием GNU sed
, а не OS X и, конечно же, не AIX, извините.)
Ответ 2
Это должно работать -
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
Это может сработать для вас:
sed '/year/,/_cons/{//!d}' file
или
awk '/_cons/{p=0};!p;/year/{p=1}' file
Ответ 4
Вы можете сделать это визуально.
Просто откройте файл с помощью gVim
и выполните команду:
:g/^\s*year/+1,/^\s*_cons/-1 d
Объяснение:
-
g
глобальная команда
-
/^\s*year/+1
строка соответствия ниже year
-
/^\s*_cons/-1
строка соответствия выше _cons
-
d
удалить диапазон
Ответ 5
Подводя итоги и обобщаем два решения GNU sed, которые работают:
sed '/BEGIN/,/END/{/BEGIN/!{/END/!d;}}' input.txt
sed '/BEGIN/,/END/{//!d}' input.txt