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

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

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

变量 myvar与引号一起存储。说实话,我觉得这很愚蠢。引号只是用来告诉字符串的开始和结束位置,而不是作为值本身的一部分存储。
我怎样才能防止这种情况发生?

谢谢。

111654 次浏览

尝试使用转义字符“ ^”,例如。

set myvar=c:\my music ^& videos

在展开 myvar 时要小心,因为 shell 可能不会将 & 作为文字处理。如果上面的方法不起作用,也可以尝试在字符串中插入一个插入符号:

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

使用 jscript。

很久以前(大约8年左右) ,我正在从事一个大型的 C + +/VB6项目,我有各种各样的批处理脚本来完成构建的一部分。

然后有人指给我看 乔尔 · 泰斯特,我特别着迷于第二点,并开始把我所有的小构建脚本集成到一个单一的构建脚本中... ..。

这几乎让我心碎,让所有这些小脚本一起工作,在不同的机器上,用稍微不同的设置,耶,上帝,这是可怕的-特别是设置变量和参数传递。它真的很脆,一点点东西都会把它弄断,需要30分钟的调整才能再次启动。

最终-我可以固执我-我把所有东西都扔进去了在大约一天的 用 JavaScript 重写了所有代码,运行它从命令提示符与 CScript。

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

这取决于您希望如何使用变量。如果只想使用变量的值而不使用引号,那么可以使用延迟展开和字符串替换,或者使用 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. Using the for command to use the value of the variable without quotes, but you'll have to surround the variable with quotes when using it in commands:

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

Long story short, there's really no clean way to use a path or filename that contains embedded spaces and/or &s in a batch file.

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

注意,引号在 myvar 之前开始,实际上就是这么简单。 注意: myvar 不能在后面回显,除非它包装在引号中,因为 & 将作为命令分隔符读取,但它仍然作为路径工作。

“可变名称可包括空格”下的 http://ss64.com/nt/set.html

这是正确的做法:

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

引号将不包括在变量值中。

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

你的剧本应该写成这样:

@echo OFF


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

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

使用 CMD 提示符有时看起来很深奥,但是命令解释器实际上非常坚定地遵守它的内部逻辑,您只需要重新考虑一些事情。

事实上,set 命令根本不要求你使用引号,但是不管是你赋值变量的方式,还是不使用引号的方式,都会导致你的变量周围有额外的空格,这在调试脚本的时候是很难注意到的。

例如,以下两种方法在技术上都是有效的,但是你可以使用尾随空格,所以这不是一个好的做法:

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

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

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

这两种方法都没有留下任何可以解释的地方,变量将拥有您正在寻找的数据。

Strong text 但是,出于您的目的,只有引号方法才能有效地工作,因为您使用的是保留字符

因此,你可以使用:

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

但是,即使变量 IS 正确地设置为这个字符串,当您使用 ECHO 命令时,命令解释器将把与符号解释为关键字,以指示后面的另一个语句。

因此,如果你想从变量中回显字符串,CMD 解释器仍然需要被告知它是一个文本字符串,或者如果你不想引号显示你必须做以下之一:

回显变量 WITHQuotes:

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>

两种解决方案:

  1. 不要在路径名(目录或文件名)中使用命令解释器特有的空格或其他字符。如果您只使用字母、数字、下划线和连字符(以及扩展名之前的一个句点来标识文件类型) ,那么您的脚本生活将变得非常简单。

    多年来,我编写并收集了大量的工具,包括一个可以重命名文件的 DOS 实用程序。(一开始它只是从文件名中删除空格,但后来变成了替换文件名中的字符或字符串,甚至是递归地替换。)如果有人感兴趣,我将得到我长期忽视的网站上运行和张贴这一点和其他。

    也就是说,变量不仅仅用于保存路径名,所以..。

  2. 正如其他人已经指出的那样,对于这样一个变量值,设置“ myvar = c: my music & video”是正确的解决方案。(是的,我说的是变通。我同意你最初的倾向只是引用价值(“我的音乐和视频”)是更直观的,但它是什么,因为他们说。