Как найти линии, соответствующие шаблону, и удалить их?

14

В файле с большим количеством строк я хочу удалить строки, которые начинаются с HERE IT IS.

Как я могу сделать это, используя только инструменты командной строки?

micgeronimo
источник
2
Хотя и немного нетрадиционно, вы можете использовать vimвот так vim '+g/^HERE IT IS/d' +wq test.txt
:;
@ Doorknob, спасибо, что указали на это. На самом деле я нахожусь на пути к использованию vim
micgeronimo

Ответы:

28

Попробуй sed:

sed -i '/^HERE IT IS/d' <file>

ВНИМАНИЕ: лучше сделать резервную копию при использовании -iпереключателя sed:

sed -i.bak '/^HERE IT IS/d' <file>

Исходный файл останется таким же, как <file>.bakи измененный файл <file>.

heemayl
источник
Как я могу поставить символ новой строки после совпавшей строки и записать в новую строку?
micgeronimo
2
sed -i 's/^HERE IT IS/HERE IT IS\n/' <file>
Heemayl
1
@micgeronimo: рад помочь. Проверьте мои правки, пожалуйста.
Heemayl
6
@micgeronimo старайтесь задавать вопрос, на который вы действительно хотите получить ответ в исходном вопросе (помните, что вы можете его редактировать), а не через комментарии, которые могут быть очищены / удалены. Вы можете использовать sed '/^HERE IT IS/G' file.
Steeldriver
1
Использование SED настолько профессионально.
ЛакшьяАг
18

В дополнение к очень хорошим grepи sedполученным ответам, вот некоторые другие инструменты, которые могут сделать то же самое:

  • Несколько способов Perl:

    perl -ne '/^HERE IT IS/ || print' file > newfile
    perl -ne 'print if !/^HERE IT IS/' file > newfile
    perl -ne 'print unless /^HERE IT IS/' file > newfile
    

    Вы можете добавить -iпереключатель в любой из примеров для редактирования файла на месте:

    perl -i.bak -ne '/^HERE IT IS/ || print' file        
    
  • (Г) AWK

    awk '!/^HERE IT IS/' file > newfile
    

    Более новые версии (4.1.1 и позже) GNU awk (по умолчанию awkв Linux) также могут редактировать файл на месте:

    gawk -i inplace  '!/^HERE IT IS/' file
    
  • Shell ( bash, zsh, ksh, вероятно , другие). Это немного глупо, но это можно сделать, но другие инструменты лучше.

    while IFS= read -r line; do 
      [[ $line =~ ^"HERE IT IS" ]] || printf "%s\n" "$line"
    done < file > newfile
    
terdon
источник
1
Вы просто хвастаетесь! ;-) (но у вас есть голос, потому что он умный, я многому научился, и bashтот сделал меня
лол
bash, который следует использовать printf "%s\n" "$line": заключать в кавычки $ line для сохранения пробелов и избегать некоторых проблем с эхом (интерпретация специальных символов и т. д.). и избегает необходимости добавлять --тоже.
Оливье Дюлак
@ OlivierDulac достаточно честно. Я не хотел усложнять вещи для крайних случаев, но, так как Cuanglm добавил, IFS=и -rя могу также пройти весь путь и сделать его надежным.
Тердон
@terdon: это все к лучшему доброму ^^ (и я уже сделал +1, хотя, это очень информативно для начинающих)
Оливье Дюлак
2
@OlivierDulac Я могу заверить вас, что если бы я писал на Unix и Linux, я бы использовал printf, IFS =, -r и цитирование :). Я часто упрощаю вещи для аудитории АС, которая часто менее комфортна с командной строкой.
тердон
13

Я бы использовал, grepчтобы отфильтровать их. Например :

grep -v "^HERE IT IS" infile > outfile

Затем переместите выход обратно в путь.

Бен Хиллз
источник
Умное мышление
Анвар
5

sed это определенно путь.

Эта небольшая модификация команды @heemayl дала вам удаление строки, независимо от того, используется ли тот же случай в шаблоне или нет, из-за I в ссылке на шаблон.

sed -i '/HERE IT IS/Id' <file>

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

find . -maxdepth 1 -type f -exec sed -i.bak '/HERE IT IS/Id' {} +

Опция maxdepth означает, что это не будет повторяться в каталогах.

Arronical
источник
4

Другой вариант с питоном:

#!/usr/bin/env python3
[print(l, end = "") for l in open(f).readlines() if not l.startswith("HERE IT IS")]

Где f - путь к файлу между кавычками.

Якоб Влейм
источник
4

Grep

grep -P '^(?!HERE IT IS)' file

(?!HERE IT IS)отрицательное утверждение, которое заставляет механизм регулярных выражений соответствовать всей начальной границе строки ( которая обычно соответствует^ ), только если за ней не следует строкаHERE IT IS

питон

#!/usr/bin/python3
import sys
fil = sys.argv[1]
with open(fil) as f:
    for line in f:
        if not line.startswith('HERE IT IS'):
            print(line, end="")

Сохраните скрипт в файле, скажем, script.pyа затем запустите его с помощью приведенной ниже команды на терминале.

python3 script.py infile
Авинаш Радж
источник
вы можете использовать регулярные выражения, [print(l, end = "") for l in open(fil).readlines() if not re.match("HERE IT IS", l)]но это не намного эффективнее, чем startswith. Я задавался вопросом, как [print(l, end = "") for l in open(f).readlines() if not l.startswith("HERE IT IS")]не будет производить вывод в списке.
Авинаш Радж
Когда я впервые столкнулся с этим, мне это показалось странным. Он генерирует команду печати (или любое другое действие, которое вы хотите выполнить с ней) для всех элементов в определенном списке.
Джейкоб Влейм
Удаление его, просто для удовольствия :)
Jacob Vlijm
1

Вы можете использовать Vim в режиме Ex:

ex -sc 'g/^HERE IT IS/d' -cx file
  1. g глобальный поиск

  2. d удалять

  3. x сохранить и закрыть

Стивен Пенни
источник