处理Windows批处理脚本中的引号

Get*_*ree 56 windows quotes scripting batch-file

在Windows批处理文件中,执行以下操作时:

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

变量myvar与包含的引号一起存储.老实说,我发现这非常愚蠢.引号只是告诉字符串的开始和结束位置,而不是作为值本身的一部分存储.
我怎样才能防止这种情况发生?

谢谢.

小智 60

这是正确的方法:

set "myvar=c:\my music & videos"
Run Code Online (Sandbox Code Playgroud)

引号不会包含在变量值中.

  • 非常有用,虽然这个答案值得信赖http://stackoverflow.com/a/8582277/781695 (10认同)
  • 您的回答与一年前写的 [@RuskoGuyachev's](/sf/answers/600759421/) 有何不同? (2认同)

小智 52

set "myvar=c:\my music & videos"
Run Code Online (Sandbox Code Playgroud)

注意引号在myvar之前开始.实际上就是这么简单.旁注:myvar之后不能回显,除非它用引号括起来,因为&将被读作命令分隔符,但它仍然可以作为路径使用.

http://ss64.com/nt/set.html "变量名称可以包含空格"下

  • @Fowl,但随后双引号也得到了回应。 (3认同)

Pat*_*uff 35

这取决于您希望如何使用变量.如果您只想使用不带引号的变量值,可以使用延迟扩展和字符串替换,或者for命令:

@echo OFF
SETLOCAL enabledelayedexpansion

set myvar="C:\my music & videos"
Run Code Online (Sandbox Code Playgroud)

正如andynormancx所述,由于字符串包含引号,因此需要引号&.或者你可以用它逃脱它^,但我认为报价有点清洁.

如果使用字符串替换的延迟扩展,则获得不带引号的变量的值:

@echo !myvar:"=!
>>> C:\my music & videos
Run Code Online (Sandbox Code Playgroud)

您还可以使用以下for命令:

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

但是,如果要在命令中使用变量,则必须使用带引号的值或将变量的值括在引号中:

  1. 使用字符串替换和延迟扩展来使用不带引号的变量值,但在命令中使用该变量:

    @echo OFF
    SETLOCAL enabledelayedexpansion
    
    set myvar="C:\my music & videos"
    md %myvar%
    @echo !myvar:"=! created.
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用该for命令使用不带引号的变量值,但在命令中使用变量时,您必须用变量括起变量:

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

简而言之,实际上没有干净的方法来使用包含&批处理文件中的嵌入空格和/或s 的路径或文件名.

  • 不,只是一个受虐狂;) (7认同)
  • 很好的答案...但它让我头疼... (3认同)
  • @二进制担心者; 是的,批处理文件通常会这样做;) (2认同)

Ben*_*ick 8

Windows 命令解释器允许您在整个 set 命令周围使用引号(在从 NT 4.0 到 Windows 2012 R2 的每个 Windows NT 版本中均有效)

你的脚本应该写成如下:

@echo OFF

set "myvar=C:\my music & videos"
Run Code Online (Sandbox Code Playgroud)

然后您可以根据需要在变量周围加上引号。

使用 CMD 提示符有时看起来很深奥,但命令解释器实际上在遵守其内部逻辑方面表现得非常可靠,您只需要重新思考一下即可。

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

例如,以下两者在技术上都是有效的,但是您可以有尾随空格,因此这不是一个好的做法:

set myvar=some text   
set myvar="some text" 
Run Code Online (Sandbox Code Playgroud)

例如,以下两种方法都是在 Windows 命令解释器中设置变量的好方法,但双引号方法更优越:

set "myvar=Some text"
(set myvar=Some value)
Run Code Online (Sandbox Code Playgroud)

这两者都没有任何解释变量将完全具有您正在寻找的数据。

强文本 但是,出于您的目的,只有引用的方法才有效,因为您使用的是保留字符

因此,您将使用:

set "myvar=c:\my music & videos"
Run Code Online (Sandbox Code Playgroud)

但是,即使变量正确设置为该字符串,当您 ECHO 字符串时,命令解释器会将 & 符号解释为关键字以指示后面有另一个语句。

因此,如果您想从变量中回显字符串,仍然需要告诉 CMD 解释器它是一个文本字符串,或者如果您不希望显示引号,则必须执行以下操作之一:

用引号回显变量:

Echo."%myvar%"
Run Code Online (Sandbox Code Playgroud)

回显不带引号的变量:

Echo.%myvar:&=^&%
<nul SET /P="%myvar%"
Run Code Online (Sandbox Code Playgroud)

在上述两种情况下,您可以回显不带引号的字符串。下面的示例输出:

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

C:\Admin>    <nul SET /P="%myvar%"
C:\my music & videos
C:\Admin>
Run Code Online (Sandbox Code Playgroud)

  • 您始终可以通过延迟扩展以安全的方式使用变量。`echo(!myvar!` 这不需要输出的引号 (2认同)

Bin*_*ier 6

使用jscript.

许多月前(即大约8年的时间)或者我正在研究一个大型的C++/VB6项目,我有各种批处理脚本来完成部分构建.

然后有人指着我参加乔尔测试,我特别迷恋第2点,并着手将我所有的小构建脚本整合到一个单独的构建脚本中...

它几乎打破了我的心脏,让所有那些小脚本在不同的机器上一起工作,设置略有不同,你知道它是可怕的 - 特别是设置变量和参数传递.它真的很脆弱,最轻微的东西会打破它,需要30分钟的调整再次开始.

最终 - 我可能会很顽固 - 我把所有内容都放进去,并在大约一天内用JavaScript重写它,用命令提示符用CScript运行它.

我没有回头.虽然现在它是MSBuild和Cruise Control,如果我需要做一些甚至稍微涉及批处理脚本的东西,我使用jscript.

  • 这不是问题的答案,但由于我已经去过了批量文件内外的cmd.exe字符串,我完全同意你的看法.+1 (2认同)
  • 不言而喻,这些天它都是Powershell. (2认同)