2009-02-11 236 views
46

在Windows批处理文件,报价打交道时你做到以下几点:在Windows批处理脚本

set myvar="c:\my music & videos"

变量myvar包括存储与报价。老实说,我觉得这很愚蠢。引号只是为了告诉字符串开始和结束的位置,而不是存储为值本身的一部分。
我该如何防止这种情况发生?

谢谢。

+26

噢,我 - 你正在迈出第一步到真正疯狂的cmd脚本领域。祝你好运 - 你将需要它。请参阅http://stackoverflow.com/questions/180754/best-free-resource-for-learning-advanced-batch-file-usage/180767#180767了解指向一本好书和一些建议的指针。 – 2009-02-11 09:20:12

回答

43
set "myvar=c:\my music & videos" 

注意引号在myvar之前开始。其实很简单。 备注:除非用引号括起来,否则myvar将不会被回显,因为&将作为命令分隔符来读取,但它仍然可以作为路径使用。

http://ss64.com/nt/set.html

1

必须有引号,如果你设置的文本包括某些字符,包括&。如果您的文本不包括&那么你不需要报价。

例如,如果文本只是“C:\我的音乐”,那么你可以这样做:

set myvar = c:\my music 

但是因为你的文字有&您需要的报价。

编辑:

或者像戴夫在他回答说,你可以用^^^逃避问题的字符,但这种方法作为&的提防是不是你需要的唯一字符逃逸。在实践中,坚持引用而不是逃避所有问题字符要容易得多。

+0

这不是问题。问题在于引号与字符串的其余部分一起存储为值的一部分。 这是字符串连接,字符串比较和许多其他事情的问题。 – GetFree 2009-02-11 09:12:53

+0

够公平的,但如果你走的是逃跑的路线,那么确保你知道所有需要逃跑的角色。 – andynormancx 2009-02-11 09:18:15

0

尝试使用转义字符'^',例如

set myvar=c:\my music ^& videos 

你有你的时候要小心展开MYVAR因为shell可能不能治疗&作为文字。如果以上操作不起作用,请尝试将插入符号插入字符串中:

set myvar=c:\my music ^^^& videos 
6

使用jscript。

很多天以前(即大约8年的时间)我正在研究一个大型的C++/VB6项目,并且我有各种各样的批处理脚本来完成部分构建。

然后有人指我Joel Test,我特别喜欢第2点,并着手将我所有的小构建脚本合并到一个构建脚本中。 。 。它让我几乎伤了我的心,让所有这些小脚本在不同的机器上一起工作,而且设置稍有不同,上帝让它变得可怕 - 尤其是设置变量和参数传递。它非常脆弱,最轻微的事情会打破它,需要30分钟的调整才能重新开始。

最后 - 我可以固执我 - 我在大约一天重新写了这一切在JavaScript卡住了一大堆并,从cscript的命令提示符下运行它。

我还没有回头。尽管现在它是MSBuild和Cruise Control,但如果我需要做一些甚至与批处理脚本稍有关系的事情,我会使用jscript。

+2

这个问题并不是真正的答案,但是因为我已经去过了cmd的la-la-land。EXE字符串转义批处理文件内外,我完全同意你的看法。 +1 – Tomalak 2009-02-11 12:55:07

+2

不用说现在这些都是Powershell。 – 2014-10-10 08:09:49

+1

@BinaryWorrier精神,当然你会得到时间和使用假? (实际上并没有开玩笑,这太棒了)(免责声明:没有100%确定你和/或OP正在讨论构建脚本 - 只是在这里以缠扰者为基础!) – 2014-10-24 11:57:20

34

这取决于你想如何使用变量。如果你只是想使用的变量的值,不包括引号,你可以使用延迟扩展和字符串替换,或for命令:

@echo OFF 
SETLOCAL enabledelayedexpansion 

set myvar="C:\my music & videos" 

由于andynormancx状态,需要加引号,因为该字符串包含& 。或者你可以用^来逃避它,但是我认为这些报价有点干净。

如果您使用的字符串替换延迟扩展,你得到的变量的值不包括引号:

@echo !myvar:"=! 
>>> C:\my music & videos 

您还可以使用for命令:

for /f "tokens=* delims=" %%P in (%myvar%) do (
    @echo %%P 
) 
>>> C:\my music & videos 

但是,如果想要在命令中使用该变量,必须使用引用的值或将变量的值用引号引起来:

  1. 使用字符串替换和延迟扩展使用没有引号的变量的值,但是使用该变量的指令:

    @echo OFF 
    SETLOCAL enabledelayedexpansion 
    
    set myvar="C:\my music & videos" 
    md %myvar% 
    @echo !myvar:"=! created. 
    
  2. 使用for命令以使用没有引号的变量的值,但你“会在命令中使用时,它用引号括变量:

    @echo OFF 
    set myvar="C:\my music & videos" 
    
    for /f "tokens=* delims=" %%P in (%myvar%) do (
        md "%%P" 
        @echo %%P created. 
    ) 
    

长话短说,没什么使用包含嵌入式SP的路径或文件名中没有干净的方式ace和/或&在批处理文件中。

+0

好的答案。谢谢。 – GetFree 2009-02-11 13:28:53

56

下的“变量名可以包含空格”这是正确的方式来做到这一点:

set "myvar=c:\my music & videos" 

的报价将不包括在该变量的值。

2

Windows命令解释器允许您在整个set命令周围使用引号(在NT 4的每个版本中都有效)。

@echo OFF 

set "myvar=C:\my music & videos" 

然后你可以将周围的变量报价需要:0到Windows 2012 R2)

您的脚本应该只可以写成。

使用CMD提示符有时看起来很深奥,但命令解释程序在遵守它的内部逻辑时确实表现得相当稳固,您只需要重新考虑事情。

事实上,set命令根本不需要使用引号,但是您进行变量赋值的方式以及使用不引号的方法会导致变量周围有额外的空格调试脚本时很难注意到这一点。

例如两者的下方是技术上有效的,但你可以有尾随空格,所以它不是一个好的做法:

set myvar=some text 
set myvar="some text" 

例如两者的下面是在Windows命令解释器设置变量好方法,但是双引号的方法优于:

set "myvar=Some text" 
(set myvar=Some value) 

这些都留下任何的解释变量会正是你正在寻找的数据。

强大的文本但是,你的目的,只是引述方法会有效,因为你使用的是保留字符

这样的工作,你可以使用:

set myvar="c:\my music & videos" 

然而,即使变量IS正确地设置为这个字符串,当你使用ECHO时,命令解释器将把&符号解释为关键字来表示另一个语句如下。

所以如果你想呼应自变量的CMD解释仍然需要被告知这是一个文本字符串,或者如果你不想引号,以显示你必须做下列之一的字符串:

回声行情变量:

Echo."%myvar%" 

呼应变量不带引号:

Echo.%myvar:&=^&% 
<nul SET /P="%myvar%" 

在上述两种情况下,您可以重复使用没有引号括起来的只是科幻东北。下面的示例输出:

C:\Admin> Echo.%myvar:&=^&% 
C:\my music & videos 

C:\Admin> <nul SET /P="%myvar%" 
C:\my music & videos 
C:\Admin>