#python #regex #linux #sed #scripting
#python #регулярное выражение #linux #sed #сценарии
Вопрос:
Мне нужно удалить запись в следующем формате файла примера:
record {
record {
my_id_1
my_name_1
}
record {
my_id_2
my_name_2
}
record {
my_id_3
my_name_3
}
}
Нам нужно удалить все данные записи, используя уникальное значение my_id
или my_id_2
в этом случае, и ожидаемый результат должен быть:
record {
record {
my_id_1
my_name_1
}
record {
my_id_3
my_name_3
}
}
Примечание: файл не является стандартом, говорящим о пробелах, новых строках и т. Д. Но основная логика может заключаться в удалении всего, что находится между словом record
[включая одно и то же слово], которое относится только к my_id_*
строке в скобках.
Все, что я смог сделать до сих пор, это написать:
sed -n '/record/{:a;N;/}/!ba; /my_id_2/p}' file.conf
это, по сути, находит то, что мне нужно, но я не могу это удалить, я печатаю только те строки, которые хочу очистить.
sed
это мой основной вариант, но он также python
regex
может подойти, так что я могу передать его в ansible.
##########################
ЭТО ТАКЖЕ МОЯ ПОПЫТКА PYTHON
##########################
ИНСТРУМЕНТ: https://pythex.org /
используя python, это было самое близкое, что я получил:
сначала попробуйте: (?=my_id_2)([^}] )(?=})
с результатом матча:
`my_id_2 my_name_2`
затем немного изменен:
(?=record )([^}] )(?=})
с результатом матча:
Match 1
`1. record { record { my_id_1 my_name_1`
Match 2
`1. record { my_id_2 my_name_2`
Match 3
`1. record { my_id_3 my_name_3`
Спасибо.
Комментарии:
1.используя python, это было самое близкое, что я получил: первая попытка:
(?=my_id_2)([^}] )(?=})
с результатом соответствия:my_id_2 my_name_2
затем немного изменено:(?=record )([^}] )(?=})
с результатом соответствия:Match 1
1. record { record { my_id_1 my_name_1
Match 2
1. record { my_id_2 my_name_2
Match 3
1. record { my_id_3 my_name_3
Ответ №1:
Вы могли бы попробовать:
$ sed -i.bak '/record/{:a;N;/}/!ba; /my_id_2/d}' file.conf
$ cat file.conf
record {
record {
my_id_1
my_name_1
}
record {
my_id_3
my_name_3
}
}
Приведенное выше действие изменяет файл на месте и создает резервную копию файла с именем file.conf.bak
. Если вам не нужна резервная копия исходного файла, вы можете удалить .bak
из -i.bak
.
Ответ №2:
Поверьте, это делает то, что вы ищете, но оно добавляет пустую строку. Он просто заключает их в квадратные скобки как абзацы, а затем удаляет тот, у которого есть это имя записи.
sed '/./{H;$!d} ;x; /my_id_2/d' file.conf
Можно подумать, что вы могли бы просто удалить его с ; 1d
добавлением дополнительного к вашему заявлению sed.
sed '/./{H;$!d} ;x; /my_id_2/d ; 1d' file.conf
Однако это не имеет никакого эффекта, и строка 1 по-прежнему остается пустой. Вы можете преодолеть это, передав его последующей sed
команде, но это кажется ненадежным. Может быть, кто-то еще знает почему.
sed '/./{H;$!d} ;x; /my_id_2/d' file.conf | sed '1d'
Ответ №3:
Это может сработать для вас (GNU sed):
sed -E '/record {/{:a;N;/}/!ba;/my_id_2/!b;s/(record {.*)1.*/1/;t;d}' file
Используйте свой оригинальный подход, но проведите дополнительный тест с использованием greed, который в случае успеха сохраняет начало соответствующих строк. Если такого совпадения нет, вернитесь и, как и раньше, удалите всю соответствующую строку.
Примечание. Это может привести к некоторому нежелательному заполнению, удаление которого оставлено в качестве упражнения для читателя 😉