我正在为我的虚拟机做一些脚本,我正在使用cygwin。我需要设置计算机名称和IP地址。这部分很简单,按顺序:
wmic computersystem where caption=name "vm-01"
netsh interface ip set address "Local Area Connection 2" static 10.155.155.50 255.255.255.0
这在cmd.exe中工作得很好。现在我想从bash执行此操作。我想看看我正在执行的命令,所以我正在使用这个bash函数来执行它:
call() {
echo "$@"
$@
}
我以直观的方式尝试了逃避引号:
$ call wmic computersystem where caption=name \"wm-01\"
Executing (\\BOH\ROOT\CIMV2:Win32_ComputerSystem.Name="XXX")->rename()
Method execution successful.
Out Parameters:
instance of __PARAMETERS
{
ReturnValue = 87;
};
哪个不起作用(不要像我最初那样被“方法执行成功”弄错),错误代码87.
$ call netsh interface ip set address \"Local Area Connection 2\" static 10.155.155.50 255.255.255.0
另一方面,这很有效。
我设法使用
为wmic
命令解决了这个问题
$ call wmic computersystem where caption=name \'wm-01\'
Executing (\\BOH\ROOT\CIMV2:Win32_ComputerSystem.Name="XXX")->rename()
Method execution successful.
Out Parameters:
instance of __PARAMETERS
{
ReturnValue = 0;
};
哪个确实有用。我用netsh
$ call netsh interface ip set address \'Local Area Connection 2\' static 10.155.155.101 255.255.255.0
The filename, directory name, or volume label syntax is incorrect.
没有。我想要了解的是为什么一个命令需要\'
而第二个\"
?
答案 0 :(得分:2)
在这里要认识到有几件事是重要的:
引用的重要性是到shell ,而不是(通常)到正在启动的命令。在识别命令名称并切换其参数之前,shell会删除对此有意义的引号,但是在所有其他命令行处理之后。
在命令的原始文本中,只有出现的未加引号的引号对于引用来说对shell很重要。特别是,参数扩展引起的引号字符并不特殊 - 它们只代表自己。
虽然shell在执行任何扩展之前将命令行拆分为标记,但它稍后会对扩展命令执行分词。在已识别的引号内发生的扩展受到保护而不受单词拆分的影响,但同样,来自扩展引用的引号不会被识别为特殊引号;他们不能防止分词。
然后考虑这个版本的命令:
call netsh interface ip set address "Local Area Connection 2" static 10.155.155.50 255.255.255.0
bash
读取该行,将其拆分为单词,轻松执行扩展,执行单词拆分,然后执行引用删除,从而生成以下单词:
请注意"本地连接2" (没有引号)是一个单词'。第一个单词' call'是命令,剩下的单词是参数,由$@
(以及$*
和各个位置参数{{表示1}}, etc 。)在函数$1
内。
现在考虑当call()
执行命令时会发生什么:它与之前的文字分割大致相同,但在那里,连接名称被分成多个参数,并以这种方式呈现给call()
命令。
我相信你已经非常感激,但现在考虑一下你的命令的变化:
netsh
在这种情况下,call netsh interface ip set address \"Local Area Connection 2\" static 10.155.155.50 255.255.255.0
个字符会被转义,因此不会使连接名称成为单个shell字。因此,在达到"
之前就分开了。因此,您获得与以前相同的结果,除了call()
的两个参数中包含引号字符。
那么解决方案是什么?你已经差不多了。特殊参数netsh
和$@
之间的差异是它们与单词拆分的相互作用。当$*
在引号内展开时,对结果不执行单词拆分的规则是一个特殊例外 - 结果在$@
的元素之间分开,但不在内分割/ em>他们。主要目的是确切地想要做的事情:将shell的位置参数传递给另一个命令。
换句话说,使用此版本的shell函数:
$@
并使用原始命令行调用它,并使用不带引号的引号。