LINUX.ORG.RU
решено ФорумAdmin

Ansible. Замена строки, начинающейся со cпецсимвола $

 , , ,


0

1

Решил спросить у знающих людей, сам повозился, но как-то не получается. Пилю ansible playbook. Нужно в /usr/share/phppgadmin/conf/config.inc.php заменить $conf['servers'][0]['host'] = ''; на:

$conf['servers'][0]['host'] = 'localhost';

Для этого в playbook создаю task типа:

  - name: replace line
    lineinfile:
      path: /usr/share/phppgadmin/conf/config.inc.php
      regexp: ^$conf['servers'][0]['host'] ='';
      line: $conf['servers'][0]['host'] = 'localhost';

Затык в том, что строка начинается со спецсимвола $. Про экранирование в регекспах читал, но чета не получается как нужно.

Пробовал так:

^$\conf['servers'][0]['host'] ='';
^$\\conf['servers'][0]['host'] ='';
^\$conf['servers'][0]['host'] ='';

Вместо этого строка добавляется в конец файла:

 $conf['servers'][0]['host'] = 'localhost';

Только сейчас увидел, строка начинается не с выражения, а с пробелов (или tab-ов), видимо поэтому не получалось.

dopedopedope
() автор топика

Разобрался.

Нужно ставить двойное экранирование перед каждым спецсимволом, в том числе и перед [, ] - это пропустил.

Вот так - работает:

  - name: replace a line
    lineinfile:
      path: /usr/share/phppgadmin/conf/config.inc.php
      regexp: "\\$conf\\['servers'\\]\\[0\\]\\['host'\\] = '';"
      line: "$conf['servers'][0]['host'] = 'localhost';"
dopedopedope
() автор топика
Последнее исправление: dopedopedope (всего исправлений: 1)
Ответ на: комментарий от dopedopedope

Ради одного слова целую строку менять?! Такое только на OTUSовских курсах для слаборазвитых видел, ну я, конечно, сам немножко странный, но обычно делаю так:


  - name:     add localhost to config file
    replace:
         path: test.txt
         backup: yes
         regexp: "^(.*)(=)*'';"
         replace:  '\1  "localhost";'
Bajenko
()
Ответ на: комментарий от Bajenko

Слаборазвитый тут походу только ты, ему надо конкретную строку находить и этой конкретной строке менять '' на localhost, а твоя регуляка подменит '' по шаблону blablablalba = '', т.е. любую '' которую найдет и которая удовлетворяет шаблону.

anonymous
()
Ответ на: комментарий от anonymous

понятия не имею что за otus, но этот мальчик мало того что говном полил этот otus, так еще и сделал не то что надо, а сколько апломба. Кстати файл test.txt опять же у мальчика, а не человека который ищет помощи.

anonymous
()
Ответ на: комментарий от anonymous

Это был сарказм.

Нет разницы, что в примере регэкспа написано - смотреть надо в модуль. Топикстартер пытается натянуть сову на глобус, используя lineinfile вместо replace.
https://docs.ansible.com/ansible/latest/modules/replace_module.html Отсюда и весь юмор в адрес отус весьма характерная ошибка из их видеокурса.

anonymous
()
Ответ на: комментарий от anonymous

По документации lineinfile тоже вполне годится для этих целей, хотя можно и через replace, кажется никакой ошибки тут нет.

anonymous
()
file=/usr/share/phppgadmin/conf/config.inc.php; awk '/^\$conf\[.servers.\]\[0\]\[.host.\]/{sub("'"''"'", "'"'localhost'"'");}{print;}'  $file | dd bs=2M count=1 of=$file
anonymous
()
Ответ на: комментарий от anonymous

рискуешь прослыть башмакакой с портянками, нормальные пацаны на гребне волны только системами развертки и поставки пользуются, а не вот этими шаманствами.

anonymous
()
Ответ на: комментарий от anonymous

ага и регулярку нормально написать, а не это хардкод по пробелам и переносам, никто же не знает какое чувство прекрасного будет у того кто будет править файл.

anonymous
()
Ответ на: комментарий от anonymous

рискуешь прослыть башмакакой с портянками

Только шеллскрипт с сотнями эскейпинга короче аналогичного yaml-смузи раза в два. И понятнее.

Алсо, я она и есть, в свободное время от кодинга, только я на конкретно баше не пишу, я осознанно читал ман от dash и регулярно пользуюсь аналогами.

нормальные пацаны на гребне волны

От таких пацанов я ржу, особенно когда очередное yaml-чудо, настроившее гитлаб по заветам такого же js-чуда и поставленное js-чудом в пример виндоадминам, перешедшим на коляску, пару дней не может сменить простую настройку. Во время чего js-чудо, получив вербозный выхлоп в качестве пруфа того, что факап случился на их стороне, не вникая в суть вопроса, пытается меня научить пользоваться ssh чуть ли не по видео, при том, что ssh я пользовался очень давно и часто.

anonymous
()
Ответ на: комментарий от anonymous

Ну братиш, dd-то в принципе вещь не совсем очевидная и правильная (хотя может подходить для разных вещей, в чём живёт суть Unix; но возможно стоило бы взять специальную команду-программу для буферизации stdin в памяти), а регулярку можно хоть на полнотекстовую замену поменять, хоть на

while read line; do [ "line" = "$toreplace" ] && echo "$replaced" || echo "$line"; done

в пайпе, тут чувство прекрасного особо включать не надо, учитывая то, что мы меняем дефолт, который если и поменяют, то только до того, что придётся менять всё заново.

На таких маленьких кусках скриптов думать не надо, любой путь сойдёт.

anonymous
()

ОП, объясни, зачем пользоваться куцым ансиблом при живом шелле, авк и перле?

anonymous
()
Ответ на: комментарий от anonymous

Лень. Западло каждый раз убивать пол дня, чтобы раскатывать одно и то же добро с набором ништяков.

Как по мне - проще изобразить в ansible, чем перлом, шеллом и awk.

Перл - жив и молод, как Ленин.

dopedopedope
() автор топика
Последнее исправление: dopedopedope (всего исправлений: 1)
Ответ на: комментарий от anonymous

Отрубание пальцев вместо стрижки ногтей так себе развлечение, но проблема с ногтями действительно решается.

string= $conf['servers'][0]['host'] = '';

#####
$ cat test.txt
$conf['servers'][0]['host'] = '';

#####
$ cat replace.yaml 
---
- hosts: localhost

  tasks:
  
  - name:          add localhost to config file
    replace:
         path:     test.txt
         backup:   yes
         regexp:   "(\\$conf\\['servers'\\]\\[0\\]\\['host'\\].*)(=)*'';"
         replace:  '\1 "localhost";'

#####
$ cat replace2.yaml 
---
- hosts: localhost

  tasks:


  - name:          replace a line
    lineinfile:
        path:      test.txt
        regexp:    "\\$conf\\['servers'\\]\\[0\\]\\['host'\\] = '';"
        line:      "$conf['servers'][0]['host'] = 'localhost';"
#####

$ time ansible-playbook replace.yaml 

PLAY [localhost] **********************************************************************

TASK [Gathering Facts] ****************************************************************
ok: [localhost]

TASK [add localhost to config file] ***************************************************
changed: [localhost]

PLAY RECAP ****************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


real	0m5.063s
user	0m4.208s
sys	0m0.805s


#####
$ time ansible-playbook replace2.yaml 

PLAY [localhost] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [replace a line] **********************************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


real	0m6.199s
user	0m4.830s
sys	0m0.869s

на одной строке!!! Карл

real 0m5.063s против real 0m6.199s

и это я не стал ещё регулярку править

Bajenko
()
Ответ на: комментарий от dopedopedope

ну код же весь на экране твоя real 0m6.199s user 0m4.830s sys 0m0.869s

я регулярку твою специально оставил чтобы не шумел о выборе «оптимизированной» под replace

Bajenko
()
Ответ на: комментарий от Bajenko

Дальше леплю реплейсами, для начала хоть как-то бы работало.

В любом случае быстрее, чем ручками.

dopedopedope
() автор топика

Замена строки, начинающейся со cпецсимвола $

Этот символ в консоли не нужно заменять. Просто вводите свою команду в терминале. И не забывайте про sudo.

Владимир

anonymous
()
Ответ на: комментарий от dopedopedope

Западло каждый раз убивать пол дня, чтобы раскатывать одно и то же добро с набором ништяков.

Для этого существует source и функции.

Половину дня ты убиваешь потому, что у тебя мало опыта, о чём свидетельствует незнание регулярок и обращение на ЛОР за тем, что можно было почерпнуть из man regex за тридцать минут вдумчивого чтения, пятнадцать минут пролистывания и пяти минут поиска по словам (регуляркой, ага). По этой же причине ты выбрал готовый репозиторий с уже написанным кодом, т.е. твоя реальная стоимость как админа должна стремиться вниз, поскольку админ/девопс, который выполняет чужой код и не читает исходники кода и конфигов, имеет ненулевую вероятность нарваться на проблемы в виде забива на безопасность (привет майнерам, сливу данных с открытых баз, мяу-атаке, лол) и поднятия собственных лапок, когда дело доходит до нетривиальных случаев (один из примеров я описал выше).

Проще изобразить как раз на шелле, работая с шеллом, ты имеешь дело с REPL и более-менее языком программирования, пусть и игрушечным. Если в середине кода на шелле произошло что-то не так, ты в интерактивном режиме можешь прогнать код хоть по кускам, хоть целиком и понять, что делать; в случае каменной портянки такого уже не получится. Итеративное написание кода с такими каменными портянками без интерактивности превращается в пытку.

Перл - жив и молод, как Ленин.

9.5 из десяти задач этот инструмент возьмёт с лёгкостью. Не забывай, что это настоящий ЯП с явно не мёртвой системой пакетов. Для того, кто не поднимает лапки, полный скриптовый язык (не обязательно Perl) может и сгодиться, когда не хватает DSL для запуска программ и DSL для обработки текста. Но кто-то любит PCRE и пользуется перлом ещё и вместо AWK.

А так-то любой из сегодняшних скриптовых (да и не очень) языков - неграмотно составленный мусор для программистов малой степени грамотности, клюющих на любой хайп. Если период трэша м угара в Perl прошёл, то в случае Python, JS и Ruby всё только начинается или уже идёт. В этом ничего хорошего нет, говорю тебе как один раз клюнувший на пропаганду и посмотревший на (чуть) более грамотно сделанные языки.

anonymous
()
Ответ на: комментарий от Bajenko

Вы серьёзно?

$ cat > 1                                                             $conf['servers'][0]['host'] = '';                                     $ time (file=1; awk '/^\$conf\[.servers.\]\[0\]\[.host.\]/{sub("'"''"'", "'"'localhost'"'");}{print;}' $file >$file.new; cat $file.new >$file ; rm $file.new)

real    0m0.061s
user    0m0.036s
sys     0m0.016s
$ cat 1
$conf['servers'][0]['host'] = 'localhost';
$ uname  -m
aarch64
anonymous
()
Ответ на: комментарий от dopedopedope

Для экранирования строк, чтоб regexp распознавал их как «просто текст» в ansible есть фильтр regex_escape():

- name: replace a line
    lineinfile:
      path: /usr/share/phppgadmin/conf/config.inc.php
      regexp: '^{{ item.search | regex_escape() }}$'
      line: '{{ item.replace }}'
    with_items:
      - { search: "$conf['servers'][0]['host'] = '';", replace: "$conf['servers'][0]['host'] = 'localhost';" }
spirit ★★★★★
()

Используй шаблоны а не lineinfile или replace.

FireFighter ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.