удалить линии, совпадающие с шаблоном, если это повторится

Вы читаете неправильный раздел документации; посмотрите вместо этого расширение параметров оболочки .

$ {параметр ^ шаблон}

$ {параметр ^^ шаблон}

$ {параметр, шаблон}

$ {параметр ,, шаблон}

Это расширение изменяет регистр буквенных символов в параметр . Шаблон расширяется для создания шаблона так же, как при расширении имени файла. Каждый символ в развернутом значении параметра проверяется на соответствие шаблону , и, если он соответствует шаблону, его регистр преобразуется. Шаблон не должен пытаться сопоставить более одного символа. Оператор ‘^’ преобразует строчные буквы, соответствующие шаблону, в верхний регистр; оператор ‘,’ преобразует совпадающие буквы верхнего регистра в нижний регистр. Расширения «^^» и «,,» преобразуют каждый совпавший символ в развернутое значение; раскрытия «^» и «,» соответствуют и преобразуют только первый символ в раскрытом значении. Если шаблон опущен, он обрабатывается как «?», Который соответствует каждому символу. Если параметр равен «@» или «*», операция изменения регистра применяется по очереди к каждому позиционному параметру, и раскрытие является результирующим списком. Если параметр представляет собой переменную массива с нижним индексом «@» или «*», операция изменения регистра применяется по очереди к каждому члену массива, и раскрытие представляет собой результирующий список.

1
20.02.2019, 06:33
3 ответа

Обычно я бы написал это в несколько строк для разборчивости, но поскольку вы попросили один -вкладыш:

perl -ne '$head = $_ and next if /^\[/; $head and print $head and undef $head; print'
1
27.01.2020, 23:30

портативный сед; не должен использовать gnu sed, пусть ваш файл conf

 sed -E 'N;/^\[.+\]\n\[.+\]$/!P;D' conf

если gnu sed установить его на базовый портативный

sed --posix -E 'N;/^\[.+\]\n\[.+\]$/!P;D' conf
1
27.01.2020, 23:30
$ awk '/^\[/ { head = $0; next } head != "" { print head; head = "" } { print }' file
[main]
foo = bar
[option]
opt1 = opt2
opt3 = opt4
[tail]
print = true

Эта awkпрограмма сохраняет каждый найденный заголовок в переменную headи сразу же переходит к следующей строке ввода.

Если строка является не строкой заголовка, и если переменная headчто-то содержит, выводится заголовок. Затем выводится текущая строка.

Это более или менее прямой перевод ответа Эда Гримма на awk.


Более или менее прямой перевод на sed, где место хранения используется для хранения самого последнего заголовка, будет выглядеть так

/^\[/ {
    h;    # store header in hold space (overwriting)
    d;    # delete pattern space, start next cycle
}

x;                   # swap with hold space
/./ { p; s///g; };   # if non-empty, print and empty
x;                   # swap with hold space

Или, как один -вкладыш,

$ sed -e '/^\[/{ h;d; }' -e 'x; /./{ p;s///g; }' -e x file
[main]
foo = bar
[option]
opt1 = opt2
opt3 = opt4
[tail]
print = true

Альтернативный, но более короткий sedвариант, основанный на том факте, что в конце файла есть пустой раздел/заголовок:

$ sed -n -e'/^\[/{ x;/\n/p;d; }' -e H file
[main]
foo = bar
[option]
opt1 = opt2
opt3 = opt4
[tail]
print = true

При этом заголовок и другие строки, связанные с ним, сохраняются в области удержания. Когда новый заголовок найден, пространство хранения заменяется и для него выполняется проверка на наличие символа новой строки. Если он найден, он печатается. Другие строки просто добавляются к пробелу.

Как и awk, это будет выглядеть как

awk '/^\[/ { if (sect ~ ORS) print sect; sect = $0; next } { sect = sect ORS $0 }' file
0
27.01.2020, 23:30

Теги

Похожие вопросы