我有一個問題,我無法解決 vagrant 配置問題。我有一個包含反斜杠的檔案,我需要洗掉它,但 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
uj5u.com熱心網友回復:
事實證明,這個問題比你想象的要復雜。問題是您在這里進行了三個階段的字串插值。每個階段都需要正確轉義字串和反斜杠,以使最終sed命令正確:
- Ruby對 heredoc
<<-SHELL字串進行字串插值。 - 執行腳本的shell會進行自己的插值。
- Sed對您提供的正則運算式進行自己的插值。
讓我們從第 3 階段開始向后作業,以便在開始其他階段之前知道最終要求是什么。
第 3 階段 - Sed
我們知道 sed 需要在其正則運算式中轉義反斜杠。所以 sed 命令需要以下字串s/\\/ /。
那么問題就變成了:我們如何將該字串準確地提供給 sed?
第 2 階段 - 貝殼
我們知道我們必須為 sed 提供兩個反斜杠。讓我們在 shell 中運行一些測驗,看看它是如何轉義反斜杠的:
$ echo "\\"
\
啊哈。事實證明,shell (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/\\/ /' ...
看起來挺好的!
到目前為止,我們學到了什么:
- Ruby heredoc
<<-SHELL需要轉義反斜杠。 - shell(Bash 或 sh)要求對反斜杠進行轉義,除非使用單引號。
- Sed 需要兩個反斜杠。
現在我們可以正確地組裝我們的腳本了:
node.vm.provision :shell, privileged: false, inline: <<-SHELL
...
sed -i -E 's/\\\\/ /' /vagrant/control_join_file#{i 12}.sh
...
SHELL
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/475465.html
