Скрипт оболочки: Хочу удалить две последовательные строки, соответствующие шаблону, начиная с конкретной строки.

Вопрос или проблема

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

Например, содержимое файла выглядит следующим образом.

Строка1: a
Строка2: b
Строка3: c
Строка4: Имя: 123
Строка5:  xyz
Строка6: Имя: 456
Строка7:  abc

Я хочу найти строки, начинающиеся с 4-й строки, соответствующие первому шаблону строки, начинающемуся с “Имя: “, и соответствующему второму шаблону строки, начинающемуся с пробела, и удалить эти две последовательные строки.

Есть ли какой-нибудь эффективный способ сделать это в shell с использованием sed или чего-то другого?

Чтобы быть немного более ясным, я хочу удалить информацию о подписи/контрольной сумме из MANIFEST.MF.

Пример MANIFEST.MF выглядит следующим образом:
Из приведенного ниже файла манифеста я хочу удалить запись “Имя: “. где запись “Имя: ” может быть в одной строке или на 2 (или более) строках.

Изначально мое решение заключалось в том, чтобы найти первую запись “Имя: “, за которой следует запись “SHA-256-Digest: “, и удалить до конца файла. К сожалению, это решение имеет проблему удаления одной необходимой записи посередине. Например, “NetBeans-Simply-Convertible: ” также удаляется.

Теперь я хочу удалить запись “Имя: “, если она присутствует в 1 строке или запись, распространившуюся на 2 или более строк. Но я не должен терять записи такие как “NetBeans-Simply-Convertible: ” при удалении записей “Имя: “.

Я уже удаляю записи “SHA-256-Digest: ” с помощью следующей команды в файле sed -i "/^\SHA-256-Digest: /d" $manifest_file


Версия-манефеста: 1.0
Информация-версии: ....

Имя: com/abc/xyz/pqr/client/relationship/message/notifier/Relati
 onshipUpdateNotifierFactory.class
SHA-256-Дайджест: cSSyk6Y2L2F9N6FPtswUkxjF2kelMkGe4bFprcQ+3uY=

Имя: com/abc/xyz/pqr/client/relationship/ui/BaseRelationshipView
 $5.class
SHA-256-Дайджест: w9HgRjDuP024U4CyxeKPYFe6rzuzxZF3b+9LVG36XP8=

Имя: com/abc/xyz/pqr/client/impl/MofRelationshipAgentImpl.class
SHA-256-Дайджест: GwIBIU+UdPtjyRhayAVM90Eo+SwCT/kP65dI59adEnM=

Имя: com/abc/xyz/pqr/client/settings/ConvertibleProperties.class
NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}Con
 vertibleProperties
SHA-256-Дайджест: 5FszAtfpPXcLx/6FBWbfeg6E4fwFMRozV+Q+3rReATc= ...

Ожидаемый вывод:

Версия-манефеста: 1.0
Информация-версии: ....


NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}Con
 vertibleProperties

...

Подход с использованием awk:

Допустим, у нас есть следующий входной файл file.txt (при этом каждая строка содержит Строка<номер>: в качестве первого поля):

Строка1: a
Строка2: b
Строка3: c
Строка4: Имя: 123
Строка5:  xyz
Строка6: Имя: 456
Строка7:  abc
Строка8: Имя: 111
Строка9: www
Строка10: Num: 222
Строка11:  abc
Строка12: Имя: 333
Строка13:  ccc

awk '{ if ($2 == "Имя:") { 
           if ((getline l) > 0){ 
               if (l ~ /^\S+  \S+/) { next } else { print $0 RS l }               
           }
       } else { print } 
}' file.txt

Вывод:

Строка1: a
Строка2: b
Строка3: c
Строка8: Имя: 111
Строка9: www
Строка10: Num: 222
Строка11:  abc

‘getline var’ – считывает следующую запись из ввода awk в переменную var

Команда getline возвращает 1, если находит запись, и 0, если она встречает конец файла.

Вы видите, что то, что вы спрашиваете, неясно: один ответ удаляет 4 строки (две совпадающие и две последующие); другой удаляет всё кроме совпадающих строк…

Я скажу, что я понимаю, что вы хотите: я удаляю 2 строки, одну, соответствующую Имя: 123, и последующую. Я делаю это с помощью sed:

sed -e '/Имя: 123/{N;d}' название_файла

Используя ed:

$ printf '%s\n' 'g/^ / s///\' '-,.j' 'g/^Имя: /d' 'g/SHA-256-Дайджест: /d' '4,$g/^$/d' ,p Q | ed -s файл
Версия-манефеста: 1.0
Информация-версии: ....

NetBeans-Simply-Convertible: {com/abc/xyz/pqr/client/settings}ConvertibleProperties

Это применяет следующий скрипт редактирования к вашему входному файлу:

g/^ / s///\
-,.j
g/^Имя: /d
g/SHA-256-Дайджест: /d
4,$g/^$/d
,p
Q

Это состоит из шести отдельных команд:

  1. Две команды s/// и -,.j применяются к каждой строке, которая начинается с пробела. Пустое регулярное выражение в команде s повторно использует выражение ^ из предшествующей команды g, которая используется для применения одной или нескольких команд к строкам, соответствующим регулярному выражению, поэтому команда s удаляет первый пустой пробел на строках, которые начинаются с пустых пробелов. Затем команда j соединяет измененную строку с предыдущей строкой. Это эффективно отменяет перенос строк в вводимых данных.

  2. Команда d применяется ко всем строкам, которые начинаются с Имя: , удаляя их.

  3. Аналогично, строки, начинающиеся с SHA-256-Дайджест: , удаляются.

  4. Пустые строки удаляются начиная с 4-й строки.

  5. Мы выводим полный буфер на стандартный вывод, чтобы отобразить результат.

  6. Q завершает работу редактора безусловно (вы можете использовать wq, чтобы записать изменения обратно в исходный файл).

sed -e '
   4,$!d;      # пропустить нерелевантную часть
   /Имя:/N;    # взять строку, следующую за Имя:
   /\n.* /d;   # то, что мы искали, не это
   P;D
' ваш_файл

Ответ или решение

Для удаления двух последовательных строк, соответствующих определённым шаблонам, начиная с конкретной строки в файле, можно использовать стандартные инструменты командной строки, такие как sed или awk. В данном случае мы сосредоточимся на awk, так как он предоставляет удобный способ обработки и фильтрации текстовых данных.

Пример задачи

Для демонстрации предположим, что у вас есть файл file.txt с таким содержимым:

Line1: a
Line2: b
Line3: c
Line4: Name: 123
Line5:  xyz
Line6: Name: 456
Line7:  abc
Line8: Name: 111
Line9: www
Line10: Num: 222
Line11:  abc
Line12: Name: 333
Line13:  ccc

Цель

Ваша цель состоит в том, чтобы удалить строки, начинающиеся со слова "Name:" и следующие за ними строки (которые могут быть пустыми или содержать пробелы) для всех записей, начиная с четвёртой строки.

Решение с использованием awk

Вот пример команды awk, которая справляется с этой задачей:

awk 'NR>=4 { 
    if ($1 == "Name:") { 
        getline; 
        next; 
    } 
    print; 
}' file.txt

Разбор кода

  1. NR>=4 – этот условный оператор гарантирует, что операции будут выполняться только с четвёртой строки и дальше.
  2. if ($1 == "Name:") – проверяет, начинается ли текущая строка со слова "Name:".
  3. getline – считывает следующую строку, что позволяет нам пропустить её и не выводить.
  4. next – пропускает текущую итерацию, переходя к следующей строке.
  5. print – выводит все строки, которые не соответствуют условиям удаления.

Пример выполнения

Используя приведённую выше команду, вы получите следующий вывод:

Line1: a
Line2: b
Line3: c
Line8: Name: 111
Line9: www
Line10: Num: 222
Line11:  abc

Удаление конкретного шаблона

Если вы хотите удалить также строки, которые идут непосредственно после "SHA-256-Digest:", и гарантировать, что такие строки не будут удалены, используйте следующую конструкцию:

awk '/^Name:/ { 
    getline; 
    next; 
} 
/^SHA-256-Digest:/ { 
    next; 
} 
{ 
    print; 
}' file.txt

Изменения в формате файла "MANIFEST.MF"

Для файла, подобного вашему MANIFEST.MF, где строки могут быть перенесены, например:

Name: com/abc/xyz/pqr/client/relationship/message/notifier/Relati
 onshipUpdateNotifierFactory.class
SHA-256-Digest: cSSyk6Y2L2F9N6FPtswUkxjF2kelMkGe4bFprcQ+3uY=

Вам может понадобиться дополнительно объединить строки, которые были разбиты.

Заключение

Эти команды помогут вам эффективно удалить нужные строки из текстового файла, сохранив при этом структуру других данных. Используя awk или аналогичные инструменты, вы можете легко управлять текстовыми файлами в автоматизированных сценариях. Этот подход обеспечивает гибкость и точность в обработке данных, что является важным аспектом для IT-специалистов.

Оцените материал
Добавить комментарий

Капча загружается...