Подробный разбор алгоритма работы цикла.
# 1. h - Запись буфера 1 в буфер 2 (буфер 2 - hold space (область удержания).
# 2. : - Безадресная команда. Она задает метку, для перехода командами t, T, и b.
# 3. : b_label - инициализация метки
# 4. $ - означает последнюю строку в последнем файле
# (или последнюю строку обрабатываемого файла , если файл один)
# 5. b [LABEL] - Безусловный переход на метку LABEL.
# Если LABEL не применяется, то завершает этот
# цикл, и начинается следующий.
# 6. b - Здесь команда "b" используется без указания МЕТКИ, поэтому завершается этот цикл
# и начинается следующий или выход из скрипта, если обрабатываемый файл
# был последним или один.
# 7. $ b - эта связка означает, как только обработается последняя строка данного файла
# происходит печать Буфера 1 и выход из данного файла (если это был последний
# обрабатываемый файл или файл был только один.
# Другими словами, данная команда в скрипте будет использована только тогда, когда sed загрузив строку в Буфер 1, будет знать, что эта строка последняя в обрабатываемом файле.
# 8. N - выполняет добавление следующей строки к буферу 1.
# новая строка не затирает буфер, а добавляется к нему через символ перевода
# строки - \n.
# То есть команда "N" из обрабатываемого файла сама берет следующую строку
# в данном случае 2-ю строку и помещает ее также в Буфер 1, в котором еще
# находится предыдущая строка, в данном случае 1-я строка,
# разделяя их "\n" - символом перевода строки
# Таким образом в Буфере 1 будет такая запись : "1-я строка\n2-я строка"
#
# В данном случае это выглядит так :
# - в обрабатываемом файле 2 одинаковых строки, идущих подряд
# 1-я строка называется - "Шаблон"
# 2-я строка то же называется - "Шаблон"
# Начинается работа скрипта, и - в Буфер 1, помещается 1-я строка,
# которая называется "Шаблон"
# Далее команда "h" - Записывает содержимое буфера 1 в буфер 2, поэтому в Буфер 2
# помещается копия 1-й строки, которая называется "Шаблон"
# Далее команда "N" из обрабатываемого файла сама берет следующую строку
# в данном случае 2-ю строку и помещает ее также в Буфер 1, в котором еще находится
# предыдущая строка, в данном случае 1-я, разделяя их "\n" - символом перевода строки
# Таким образом в Буфере 1 будет такая запись : "Шаблон\nШаблон"
# После этого выполняется набор команд указанных в фигурных скобках { ...commands ...}, но только
# в том случае, если верно регулярное выражение, которое как фильтр через себя
# пропустит строку находящуюся в Буфере 1
# 9. /^(.*)\n\1$/ - это /regexp/ - образец "регулярного выражения"
# по которому исследуется строка содержащаяся в Буфере 1
# ^ - от начала строки найти (.*) - любое количество любых символов,
# кроме символа перевода строки
# затем должен быть найден символ перевода новой строки \n,
# а затем ищется \1 - точно такие же символы (идентичные), которые
# были найдены согласно
# подвыражению (.*) и все это смориться до окончания текущей строки
# Таким образом строка в Буфере 1 - "Шаблон\nШаблон" соответствует заданному
# образцу "регулярного выражения" - /^(.*)\n\1$/
# Поэтому далее выполняется блок команд { g; b b_Label }
# 10. g - данная команда , из Буфера 2 копирует строку в Буфер 1,
# при этом затирая строку которая находится в Буфере 1 на момент данной операции
# Например, в данный момент в Буфере 2 находится строка - "Шаблон"
# и эта строка затрет строку "Шаблон\nШаблон"
# Таким образом и происходит удаление дубликатов строк, но если они
# идут сразу друг за другом.
# 11. b b_label - эта команда выполняет безусловный переход на метку : b_label, и
# начинается следующий цикл обработки строк данного файла.
# 12. Если в Буфер 1 попали строки разные, например "Строка\nШаблон",
# тогда пропускается выполнениe блока команд { g; b b_Label }
# 13. P - выполняется данная команда. Эта команда выводит содержимое
# Буфера 1 в выходной поток, (в данном случае печатает на экран)
# однако выводится из Буфера 1 только 1-я строка, от начала до первого \n,
# а именно, (напомню в Буфере 1 у нас в данный момент 2 разных строки
# "Строка\nШаблон"), выводится строка "Строка"
# 14. D - эта команда только что-выведенную строку удаляет из Буфера 1,
# то есть смещает курсор за символ \n и печатается строка "Шаблон"
# Получается так "Строка\nШаблон", то есть 1-я подстрока данной строки
# «Строка\n» - не печатается, а печатается 2-я подстрока данной строки «Шаблон»
# данный цикл закончен и начинается следующий, пока не закончатся обрабатываемые строки.
искал долго ответ, на форумах не очень хотят помогать