Следующие сценарии sed основаны на идее, что строка, содержащая ноль -или -дополнительных пробелов и строка «задача Listen», определяет начало блока текста, который вы хотите отредактировать, и что блок продолжается до следующей «задачи» или до конца файла (, в зависимости от того, что наступит раньше ).
Это работает в тех случаях, когда строка 'edit TRIES 2' может не следовать сразу за строкой task Listen
, а может быть в любом месте в блоке task Listen
.
Он также справится с вариациями количества пробелов в строке edit TRIES 2
.
sed -E -e '/^ *task Listen/,/^ *task/ {s/edit +TRIES +2 *$/edit TRIES 3/}'
Расширенные регулярные выражения включены (с -E
), поэтому мы можем использовать+
(1 -или -больше )без необходимости использовать обратную косую черту. Также используется для чередования (task|xyz)
без искажения обратной косой черты во втором примере.
*$
в конце регулярного выражения поиска гарантирует, что оно будет соответствовать только 2, а не какому-либо другому числу, начинающемуся с 2.
Например, если ввести это:
$ cat input.txt
task something
edit TRIES 2
task Listen
foo
bar
edit TRIES 25
edit TRIES 2
task somethingelse
edit TRIES 2
Будет получен следующий результат:
$ sed -E -e '/^ *task Listen/,/^ *task/ {s/edit +TRIES +2 *$/edit TRIES 3/1}' input.txt
task something
edit TRIES 2
task Listen
foo
bar
edit TRIES 25
edit TRIES 3
task somethingelse
edit TRIES 2
Обратите внимание, что a )не изменил ПОПЫТКИ 2 на ПОПЫТКИ 3 ни в предыдущем, ни в последующем блоке задач, а b )изменил ПОПЫТКИ 2 везде, где он появлялся в «задаче». Блок «Слушай». ПРИМЕЧАНИЕ. :, если в этом блоке более одного раза встречается «edit TRIES 2», все вхождения будут изменены.
Если блок «Прослушивание задачи» завершается или может заканчиваться чем-либо, кроме строки, начинающейся с нуля -или -дополнительных пробелов и слова «задача», вы можете изменить второй адрес в соответствии с. например. если блок может заканчиваться либо новым блоком задачи, либо блоком "xyz":
sed -E -e '/^ *task Listen/,/^ *(task|xyz)/ {s/edit +TRIES +2 *$/edit TRIES 3/1}'
Чтобы заставить любую из приведенных выше команд sed фактически изменить входной файл, а не только выходной поток,используйте опцию sed -i
.
Наконец, если вводимый текст может содержать пробелы и/или символы табуляции вместо просто пробелов, вы можете использовать класс символов [[:blank:]]
для их сопоставления. например.
sed -E -e '/^[[:blank:]]*task Listen/,/^[[:blank:]]*task/ {
s/edit[[:blank:]]+TRIES[[:blank:]]+2[[:blank:]]*$/edit TRIES 3/}'
или, если ваша версия sed поддерживает perl -совместимые регулярные выражения (, например. GNU-сед):
sed -E -e '/^\s*task Listen/,/^\s*task/ {s/edit\s+TRIES\s+2\s*$/edit TRIES 3/}'
Таким образом, из моего исследования темы, о которой я мало что знаю :, невозможно напрямую редактировать файл конфигурации, используя только virsh.
После быстрого погружения в Python я смог собрать этот скрипт, который выполняет свою работу
#!/usr/bin/python3
import xml.etree.ElementTree as ET
import libvirt
import sys
import os
desired_number_of_monitors = 3
domain_name = 'win10'
remote_viewer_config_path = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'remote-viewer-win10-connection.ini')
if not os.path.exists(remote_viewer_config_path):
print(f'could not find {remote_viewer_config_path}: try again')
sys.exit(1)
if len(sys.argv) >= 2:
desired_number_of_monitors = int(sys.argv[1])
try:
libvert_con = libvirt.open(None)
except libvirt.libvirt.libvirtError:
print('Failed to open connection to the hypervisor')
sys.exit(1)
try:
win10_domain = libvert_con.lookupByName(domain_name)
except libvirt.libvirtError:
print(f'Failed to find domain {domain_name}')
sys.exit(1)
try:
raw_xml = win10_domain.XMLDesc(0)
except libvirt.libvirtError:
print(f'Failed to get xml from domain {domain_name}')
sys.exit(1)
try:
tree = ET.ElementTree(ET.fromstring(raw_xml))
devices = tree.find('.//devices')
#remove all video nodes
for v in devices.findall('video'):
devices.remove(v)
#add the desired number of video nodes
while desired_number_of_monitors > len(devices.findall('video')):
video = ET.Element('video')
video.append(ET.fromstring("<model type='qxl'></model>"))
video.append(ET.fromstring("<address type='pci'></address>"))
devices.append(video)
#the updated xml configuration
output_xml = ET.tostring(tree.getroot(),encoding='unicode')
except Exception as e:
print(f'failed to edit the xml for {domain_name} : {e}')
try:
win10_domain = libvert_con.defineXML(output_xml)
#if the domain is running stop exit
if win10_domain.isActive():
print(f'{win10_domain.name()} is running: try again')
sys.exit(1)
else:
#start the vm? am I actually re-creating the vm or just starting it and does it matter
if win10_domain.create() < 0:
print(f'Failed to start the {win10_domain.name()} domain')
else:
print(f'{win10_domain.name()} vm started')
os.system(f'remote-viewer -f {remote_viewer_config_path}')
except Exception as e2:
print(f'failed to start update or start {domain_name} : {e2}')