根据标题,是否可以获取用于调用ruby脚本的原始命令行?
我直接调用命令后,我所遵循的确切行为类似于SSH:
ssh somehost -- ls -l
SSH将在服务器上运行“ls -l”。它需要被解析,因为如果shell已经解释了引号并执行了扩展等,那么命令可能无法正常工作(如果它包含引号等)。这就是ARGV不好的原因;报价被剥夺了。
考虑以下示例:
my-command -- sed -e"s/something/something else/g"
ARGV包含以下内容:
--
sed
-es/something/something else/g
sed命令将失败,因为引号将被剥离,替换命令中的空格意味着sed将不会看到“else / g”。
那么,要重新迭代,是否可以获取用于调用ruby脚本的原始命令行?
答案 0 :(得分:3)
不,这是在操作系统级别。
您可以尝试简单地引用整个输入:
my-command -- "sed -e\"s/something/something else/g\""
在Ruby中,可以这样使用:
ruby -e "puts ARGV[0]" -- "sed -e\"s/something/something else/g\""
(output) sed -e"s/something/something else/g"
或者,在文件putsargv1.rb
中(内容为puts ARGV[1]
):
ruby -- "putsargv1.rb" "sed -e\"s/something/something else/g\""
(output) sed -e"s/something/something else/g"
答案 1 :(得分:1)
你的例子被误导了。 ssh somehost -- ls *
将在localhost上扩展*
(例如ls localfile1 localfile2 localfile3
),然后在远程主机上执行该操作,结果导致很多ls: cannot access xxx: No such file or directory
错误。 ssh
没有看到未解释的命令行。
正如您所说,您将获得-es/something/something else/g
作为单个参数。这正是sed
所能获得的。实际上,这与您撰写-e"s/something/something else/g"
和"-es/something/something else/g"
以及-es/something/something\ else
时所获得的内容相同。
使用此事实,您可以使用Shellwords.shellescape
“保护”空格和其他不可用的内容,然后再将其移交给外部进程。您无法获得原始行,但您可以确保保留语义。
答案 2 :(得分:0)
Shellescape在args上工作但是并没有完全模仿SSH。采用以下示例(请参阅下面的test.rb内容):
ruby test.rb -- ls -l / \| sed -e's/root/a b c/g'
这将使用shellescape方法失败,但使用SSH成功。我选择手动转义引号和空格。可能会有一些边缘情况无法捕获,但它似乎适用于大多数情况。
require 'shellwords'
unparsed = if ARGV.index('--')
ARGV.slice(ARGV.index('--') + 1, ARGV.length)
end || []
puts "Unparsed args: #{unparsed}"
exit if unparsed.empty?
shellescaped = unparsed.map(&Shellwords.method(:shellescape)).join(" ")
quoted = unparsed.map do |arg|
arg.gsub(/(["' ])/) { '\\' + $1 }
end.join(" ")
puts "Shellescaped: #{shellescaped}"
puts `bash -c #{shellescaped.shellescape}`
puts "Quoted: #{quoted}"
puts `bash -c #{quoted.shellescape}`
感谢您的回答:)