У меня есть файл конфигурации, который содержит несколько записей.
Используя bash, как мне найти New
и удалить его и все записи, относящиеся к нему.
Test {
blah..
site {
id
}
location {
id
}
staff {
access {
}
}
}
New {
blah..
site {
id
}
location {
id
}
staff {
access {
}
}
}
Link {
blah..
site {
id
}
location {
id
}
staff {
access {
}
}
}
в результате чего
Test {
blah..
site {
id
}
location {
id
}
staff {
access {
}
}
}
Link {
blah..
site {
id
}
location {
id
}
staff {
access {
}
}
}
Я знаю, что могу использовать grep
, чтобы найти совпадающие результаты, но как мне удалить его?
Например:
grep -m 1 -A25 New test.txt
редактировать Похоже, это работает, чтобы удалить вывод и дать правильный результат.
grep -m 1 -A25 New test.txt > test | grep -v -x -f test test.txt
но оставляет избыточный файл test
и исходный файл не обновляется.
Есть ли лучший способ сделать это, чтобы не было избыточного файла и обновлялся исходный файл?
Формат вашего файла не очевиден, но что-то вроде sed '/New/,/^}$/d' file
подойдет для примера, который вы показываете.
@GillesQuénot это из собственного домашнего сценария. Над чем я не властен.
@tripleee, к сожалению, это не работает.
Вы можете попробовать что-то вроде awk '/^New/{f=1}/^Link/{f=0}{if (f==1){next}}1' file
@j_b спасибо, это будет работать, только если следующая запись содержит Link
, обычно это не так..
Альтернативная версия, не зависящая от наличия «Ссылки»: awk '/^New/{f=1}/^}/&&f==1{f=0}{if (f==1){next}}1' file
@Tom Это работает для образца, который вы действительно опубликовали. Есть ли различия между тем, что вы разместили в пробелах и т. д.?
У меня работает команда sed 's/^New/,/^}/d'
. Это результат, когда я вставляю через него ваш образец:
Test {
blah..
site {
id
}
location {
id
}
staff {
access {
}
}
}
Link {
blah..
site {
id
}
location {
id
}
staff {
access {
}
}
}
Вы можете разделить пространство между закрытием }
и открытием \w+[^{]*{
с помощью этого регулярного выражения:
/(?<=^\})[^{]*?(?=\w+[^{]*{)/gm
Когда у вас есть блоки, отфильтруйте New
. Вот демонстрация Ruby:
ruby -e 'puts $<.read.
split(/(?<=^\})[^{]*?(?=\w+[^{]*{)/).
select{|b| b[/\w+/]! = "New"}' file
Но вы можете сделать то же самое с Perl, Python и т. д.
Альтернативно, Perl:
perl -0777 -pE 's/^New[\s\S]*?\}\s*(?=^\w+\h*\{)//gm' file
Демонстрация регулярного выражения
Использование awk
:
awk '/^New/{f=1} /^}/&&f==1 {f=0;next} !f' file.txt
Выход:
Test {
blah..
site {
id
}
location {
id
}
staff {
access {
}
}
}
Link {
blah..
site {
id
}
location {
id
}
staff {
access {
}
}
}
Спасибо. Хорошо поймал. Будет обновляться соответственно
mawk 'BEGIN { FS = RS "*New {"
ORS = RS = RS "}" RS } NF < 2'
1 Test {
2 blah..
3
4 site {
5 id
6 }
7 location {
8 id
9 }
10 staff {
11 access {
12
13 }
14 }
15 }
16
17 Link {
18 blah..
19
20 site {
21 id
22 }
23 location {
24 id
25 }
26 staff {
27 access {
28
29 }
30 }
31 }
Как насчет Perl-решения с использованием recursive regex
:
perl -0777 -pe 's/\bNew\s*(\{(?:[^{}]+|(?1))*})//' test.txt
Шаблон соответствует последовательности строк New
, за которыми следует сбалансированный
набор фигурных скобок:
[^{}]+
соответствует любым символам, кроме фигурных скобок.(?1)
указывает механизму регулярных выражений вставлять шаблон в скобках
(упомянутый ниже) на этой должности.(?:[^{}]+|(?1))
— это чередование узоров выше.(\{(?:[^{}]+|(?1))*})
заключен в пару фигурных скобок
и на него ссылается (?1)
рекурсивно, чтобы шаблон соответствовал
вложенные пары фигурных скобок.
Из какого инструмента/языка исходит этот вывод?