Ошибка удаленной отправки для изменения файла

Относительно короткое решение с использованием утверждений отрицательного просмотра вперед в регулярном выражении perl:

perl -p0e 's/(ip=)[^\n]*((?:(?!ip=).)*?host=c)/\1new_ip_for_host_c\2/gs' hosts.txt

Пояснение:

Сначала используется цикл печати -с использованием опции -p. Это перебирает строки файла, предоставленного в качестве аргумента для perl, и печатает их. Если строка изменена, печатается измененный вариант,как с sed.

Содержимое файла на самом деле не обрабатывается как отдельные строки, опция -pпросто служит для того, чтобы заставить perlсразу читать файл и использовать содержимое в качестве строки по умолчанию для сопоставления без использования переменной. Это достигается с помощью параметра -0, который заставляет perlобрабатывать многострочный ввод как одну строку, заменяя символы новой строки нулевыми байтами.

В шаблоне сохраняются части, за исключением изменяемого значения.

Значение распознается как любое до следующей новой строки, которая, как я предполагаю, понимается как следующий нулевой -байт в этой ситуации. Кто-то, кто знает это, возможно, может объяснить.

Затем, используя утверждение отрицательного просмотра вперед, сопоставляются все символы, которым не предшествует часть ip=, пока не встретится часть host=d. Это необходимо, иначе perl предпочел бы наиболее левое -совпадение кратчайшему и сопоставлялся бы с самой первой ip=до требуемой host=cчасти.

Символы, которым не предшествует ip=, сопоставляются не -жадным образом, в противном случае, опять же, совпадение будет охватывать все, начиная с первого ip=до host=c, поскольку по умолчанию предпочтение отдается самому длинному совпадению.. Другими словами, это гарантирует, что текст сопоставляется в разделах, заканчивающихся host=cи начинающихся сегментом ip=, ближайшим к host=c, а не самым дальним.

Символ, ограниченный отрицательным опережающим выражением внутри конструкции (?:). Он обозначает не захватывающую группу -, что означает, что она не будет учитываться в общем количестве обратных ссылок в строке подстановки. Группировка используется для того, чтобы знак *мог правильно количественно оценить всю комбинацию символов с отрицательным опережением -как один атом. В примере обратные ссылки варьируются от \1-\2, в то время как без захватывающей группы, не являющейся -, они будут \1-\3, где \3обозначает вложенную группу.

Обратные ссылки \1и \2в строке подстановки — это совпадающие части раздела, которые точно содержат IP-адрес хоста, найденного в совпавшем разделе.

Таким образом, IP-адрес будет заменен на new_ip_for_host_c.

Общее блаблабла:

Я не уверен, что формат данных был выбран ОП, просто выкладывая это в общем :лучше хранить такие простые данные таким образом, чтобы записи разделялись символами новой строки, т.е. не было многострочных записей. Обратитесь к формату /etc/passwd. Большинство стандартных фильтров Unix ориентированы на строку -, и манипулирование данными становится намного проще, если вы следуете "da Unix wae". Если ваши данные являются более сложными (, вложенными элементами данных и т. д. ), вам лучше использовать такой формат, как JSON, и манипулировать им с помощью соответствующего синтаксического анализатора.

0
02.03.2021, 23:51
2 ответа

Этот ваш код требует капитального ремонта в нескольких местах.

  • Инициализация переменных окружения $OLDn $NEWдля использования без экранирования, так как они получают обратную косую черту ниже по течению, чтобы избежать двойного экранирования.
  • Экранируйте переменную $OLD var, чтобы она стала безопасной для подключения к левой стороне команды замены sed.
  • Аналогичным образом экранируйте переменную $NEW для использования в правой части замещающей команды.
  • Команда sed использует одинарные кавычки внутри одинарных кавычек под общим прикрытием двойных кавычек, поэтому они были экранированы, чтобы избежать любых одинарных кавычек в новых или старых значениях var.
#!/bin/ksh

OLD="command[Check_Memory_OS_10038]=/opt/tools/nagitem/libexec/check_mem.pl -w 80,10 -c 90,25";export OLD
NEW="command[Check_Memory_OS_10038]=/opt/tools/nagitem/libexec/check_mem_ng.sh -w 80 -c 90";export NEW
DEST1="/opt/tools/nagitem/libexec/"
DEST2="/opt/tools/nagitem/nrdp/clients/nrds/"

#--------------------
# escape variables
eOLD=$(printf '%s\n' "$OLD" | sed -e 's:[][\/^$.*]:\\&:g' -e "s:':&\\&&:g")
eNEW=$(printf '%s\n' "$NEW" | sed -e 's:[\/&]:\\&:g' -e "s:':&\\&&:g")
#--------------------

for x in `cat /home/joe/nagios/hostlist`
do
SSH_STATUS=$(ssh -n -o BatchMode=yes -o StrictHostKeyChecking=no $USER@$x "pwd" >/dev/null)
  if [[ $? = "0" ]];then
    scp -p /home/joe/nagios/check_mem_ng.sh $x:/tmp
    ssh -o "StrictHostKeyChecking no" $x "sudo /usr/localcw/bin/eksh -c '/bin/cp /tmp/check_mem_ng.sh $DEST1;chown nagitem:nagitem $DEST1/check_mem_ng.sh;cd $DEST2; /bin/sed -i -e '\\''s/$eOLD/$eNEW/g'\\'' /opt/tools/nagitem/nrdp/clients/nrds/nrds.cfg'"
else
   echo "Cannot connect to $x" >> badhosts
fi
done
0
18.03.2021, 22:27

Вы заключаете свой параметр eksh в одинарные кавычки '. Внутри одинарных кавычек нет возможности раскрывать спецсимволы. Таким образом, ваш $DESTи другие переменные не расширяются, оставляя некоторые странные остатки.

0
18.03.2021, 22:27

Теги

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