Бродячая машина не будет правильно запускать SED - Как избежать обратной косой черты в сценариях оболочки Vagrant

У меня проблема, я не могу обойти vagrant provisioning. У меня есть файл с обратной косой чертой, который мне нужно удалить, но Vagrant (Ruby?) просто не сделает этого, и я пытался уже 2 дня.

Vagrant.configure("2") do |config|  
%w{test2 }.each_with_index do |name, i|
config.vm.define name do |node|
 node.vm.provider "virtualbox" do |vb|
   vb.name = "test#{i + 2}"
   vb.memory = 512
   vb.cpus = 1
 end
 node.vm.box = "ubuntu/focal64"
 node.disksize.size = "1GB"
 node.vm.hostname = name
 node.vm.network :private_network, ip: "10.0.5.#{i + 12}"
 node.vm.provision :shell, privileged: false, inline: <<-SHELL       
   cat /vagrant/control_join_file.sh | tr -d '\\n' > /vagrant/control_join_file#{i + 12}.sh       
   sed -i -E "s@\\@ @" /vagrant/control_join_file#{i + 12}.sh
   chmod +x /vagrant/control_join_file#{i + 12}.sh 
   sudo /vagrant/control_join_file#{i + 12}.sh 
 SHELL
end
end      
end

Строка ниже является виновником, если я прокомментирую это положение.

sed -i -E "s@\\@ @" /vagrant/control_join_file#{i + 12}.sh

Я изменил разделитель на знак @ и перепробовал сотни вещей. Я действительно надеюсь, что кто-то может указать, что здесь не так.

Также, если я запускаю его так, он работает. Я могу заглянуть в созданный файл и убедиться, что 4 заменены на знаки процента. Проблема, кажется, с обратной косой чертой.

sed -i -E "s@4@%@" /vagrant/control_join_file#{i + 12}.sh

Вы пробовали обычную вещь, удваивая обратную косую черту? sed -i -E "s@\\\\@ @" /vagrant/control_join_file#{i + 12}.sh

Wiktor Stribiżew 15.05.2022 13:35
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
0
1
40
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема оказывается более сложной, чем вы думаете. Проблема в том, что у вас есть три этапа интерполяции строк. На каждом этапе необходимо правильно экранировать строки и обратную косую черту, чтобы последняя команда sed была правильной:

  1. Рубин выполняет интерполяцию строки в строке heredoc <<-SHELL.
  2. ракушка, под которым выполняется скрипт, выполняет собственную интерполяцию.
  3. Сед выполняет собственную интерполяцию предоставленного вами регулярного выражения.

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

Этап 3 - Сед

Мы знаем, что sed требует экранирования обратной косой черты в регулярном выражении. Итак, команде sed нужна следующая строка s/\/ /.

Тогда возникает вопрос: как передать именно эту строку в sed?

Этап 2 - Оболочка

Мы ЗНАЕМ, что нам нужно передать две обратные косые черты для sed. Давайте запустим некоторый тест в оболочке и посмотрим, как он избегает обратной косой черты:

$ echo "\\"
\

Ага. Оказывается, оболочка (bash) интерполирует обратную косую черту внутри двойных кавычек. Как насчет одинарных кавычек?

$ echo '\\'
\\

Ну это полезно. Это означает, что мы можем использовать одинарные кавычки, чтобы предотвратить интерполяцию обратной косой черты в Bash.

Давайте проверим это:

$ echo '\\' | sed -E 's/\/X/'
X\

Кажется, это работает. Обратите внимание, что если вы хотите заменить все обратные косые черты, вам нужно использовать модификатор g:

$ echo '\\' | sed -E 's/\/X/g'
XX

В порядке. Кажется, мы собрали все кусочки головоломки для перехода к этапу 1.

Этап 1 - Рубин

В Ruby оператор heredoc <<-SHELL выполняет собственную интерполяцию строк. Поэтому обратную косую черту необходимо экранировать.

Давайте проверим это в irb:

> puts <<-SHELL
sed -E 's/\\\/ /' ...
SHELL

sed -E 's/\/ /' ...

Выглядит неплохо!

Что мы узнали на данный момент:

  1. Ruby heredoc <<-SHELL требует экранирования обратной косой черты.
  2. Оболочка (Bash или sh) требует экранирования обратной косой черты, если не используются одинарные кавычки.
  3. Sed нужны две обратные косые черты.

Теперь мы можем правильно собрать наш скрипт:

node.vm.provision :shell, privileged: false, inline: <<-SHELL
  ...
  sed -i -E 's/\\\/ /' /vagrant/control_join_file#{i + 12}.sh
  ...
SHELL

большое спасибо за подробное объяснение. Должен сказать, что каким-то образом я уже пробовал это (пробовал до 8 обратных слэшей), но это не сработало, поэтому я продолжил. Я, должно быть, только что потерял одну часть головоломки. но благодаря вам теперь у меня все работает как надо! Я знаю, что это отняло у вас время, но я хочу, чтобы вы знали, что я очень ценю ваш подробный ответ.

user3008410 15.05.2022 16:31

Другие вопросы по теме