Удалить линии, которые не начинаются с шаблона из данного набора шаблонов

11

У меня есть файл, который содержит такие данные:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc

.. --.

Вопрос: я хочу удалить любую строку, которая не начинается со следующих строк:

report  
-th  
-to

это означает, что вывод желания удалит все эти средние ненужные точки и хэши и будет выглядеть так:

report aaaaaaaa  
-th bbbbbbbbb  
-to ccccccccc

sed/// awkи grepт.д. любое решение, которое будет работать.

Рана Хан
источник

Ответы:

15

Использование sedдля изменения файла на месте:

sed -i '/^\(report\|-t\(h\|o\)\)/!d' your_file

Это дает указание sedудалить все строки, не соответствующие шаблону. Сам шаблон ^(начало строки), сопровождается либо либо, reportлибо -tсопровождается либо hили o.

Следует отметить, что это не фактическая модификация на месте: sedсоздает временную резервную копию и перезаписывает ее исходным файлом.

Если вы хотите sedсохранить резервную копию исходного файла (что может быть хорошей идеей, если файл содержит критические данные), дайте -iкоммутатору расширение для создания файла резервной копии:

sed -i'.bak' -e '/^\(report\|-t\(h\|o\)\)/!d' your_file

изменит your_fileи создаст резервную копию оригинала под названием your_file.bak.

Примечание стороны

Пожалуйста, не истолковывайте мои намерения и не обижайтесь на это, но я заметил, что у вас есть много похожих вопросов, связанных с регулярным выражением / обработкой текста. Я советую вам начать обучение sed, awkи grepсамостоятельно, чтобы помочь ускорить вашу производительность. Опять же, не поймите меня неправильно, я слишком рад помочь (как и большинство людей здесь); просто я думаю, что вы получите огромную выгоду от приобретения этих инструментов для ежедневного использования.

Просто чтобы доказать, насколько полезны люди здесь, рассмотрите предложение @ slm в комментариях ниже и не стесняйтесь заходить в этот чат в любое время для вопросов.

Джозеф Р.
источник
1
Ваше регулярное выражение кажется излишне загадочным. Я думаю, что вы на самом деле используете больше символов, чем если бы вы только что перечислили три варианта в явном виде.
Ниспио
1
@nispio Я знаю, но это может быть более эффективным, если рассматриваемый файл большой.
Джозеф Р.
Интересно. Я всегда измерял регулярные выражения с точки зрения длины или читабельности. Я никогда не задумывался о скорости исполнения. Я не думаю, что знаю достаточно о том, как они оцениваются, чтобы судить, что быстро, но я предполагаю, что это также зависит от реализации, верно?
Ниспио
3
Повторяя слова Джозефа о готовности помочь, если у вас есть общие вопросы, которые не соответствуют стилю вопросов и ответов, вы всегда можете попробовать поговорить с нами в чате на этом сайте. chat.stackexchange.com/rooms/26/unix-and-linux . Некоторые из нас живут там 8-)
slm
@slm Спасибо за это. Я добавлю это к моему ответу.
Джозеф Р.
10

Вы можете использовать простой grep для этого:

$ grep -e '^report\|^-th\|^-to' filename
pradeepchhetri
источник
1
Это не большая экономия, но вы можете объединить -th/ -toв -t[ho].
Кевин
grep -eилиegrep
Оливье Дюлак
2

Использование sed:

sed -n -e '/^report\|^-th\|^-to/p' filename
nispio
источник
Это не большая экономия, но вы можете объединить -th/ -toв -t[ho].
Кевин
1
@Kevin Это правда. Смотрите мой разговор с Джозефом Р. в комментариях к его ответу.
Ниспио
2

Использование awk:

awk '/^report|^-t[ho]/' file
jasonwryan
источник
Это не большая экономия, но вы можете объединить -th/ -toв -t[ho].
Кевин
1

Опрашивающий сделал два замечания:

  • желая удалить любую строку, не начинающуюся с «report» или «-th» или «-to».
  • желаемый вывод должен удалить "все эти средние нежелательные точки и хэши (sic)"

Решения в настоящее время касаются первого пункта и, следовательно, второго. Но предположим, что файл больше и выглядит так:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc
anything else
.. --.
-tp ddd
-tq eee
     -  -----

Разве обращение ко второму пункту ФП не поможет?

sed -r -i.bak '/^[ |.|-]*$/d' input-file 

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


источник
0

Использование Perl:

perl -ne 'print if /^report|^-t[ho]/' filename > newfile

или, чтобы редактировать на месте (например sed, perlтакже создаст временную резервную копию, так что это не так при редактировании на месте ):

perl -i.bak -ne 'print if /^report|^-t[ho]/' filename

Это создаст копию исходного файла filename.bakи перезапишет исходный файл с отредактированной версией.

Тердон
источник