【问题标题】:Dealing with quotes in Windows batch scripts处理 Windows 批处理脚本中的引号
【发布时间】:2010-10-06 20:44:40
【问题描述】:

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

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

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

谢谢。

【问题讨论】:

  • 哦,天哪 - 您正在迈出真正令人抓狂的 cmd 脚本领域的第一步。祝你好运——你会需要它的。请参阅stackoverflow.com/questions/180754/… 以获得一本好书的指针和一些建议。

标签: windows batch-file quotes scripting


【解决方案1】:
set "myvar=c:\my music & videos"

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

http://ss64.com/nt/set.html 在“变量名可以包含空格”下

【讨论】:

  • 它实际上可以被回显,你只需要将它用引号括起来;)echo "%myvar%"
  • @Fowl 但随后双引号也会得到回应。
  • 如果您像这样包装可执行文件的路径,则需要在调用“%msbuild%”时引用它
【解决方案2】:

这是正确的做法:

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

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

【讨论】:

【解决方案3】:

这取决于您要如何使用该变量。如果您只想使用不带引号的变量值,您可以使用延迟扩展和字符串替换,或 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.
    )
    

长话短说,在批处理文件中使用包含嵌入空格和/或&s 的路径或文件名确实没有干净的方法。

【讨论】:

  • 优秀的答案。 . .但这让我头疼。 . .
  • @Binary Warrier;是的,批处理文件往往会这样做;)
  • 你一定是某种批处理文件之神。如此光荣的聪明白痴;)
【解决方案4】:

使用 jscript。

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

然后有人指点我Joel Test,我特别迷恋第 2 点,并着手将我所有的小构建脚本整合到一个构建脚本中。 . .

它几乎让我心碎,让所有这些小脚本一起工作,在不同的机器上,设置略有不同,天哪,这太可怕了——尤其是设置变量和参数传递。它真的很脆,一点点东西都会破坏它,需要 30 分钟的调整才能重新开始。

最终 - 我可以固执己见 - 我把所有东西都扔进去 大约一天后用 JavaScript 重新编写了所有内容,从命令提示符运行它使用 CScript。

我没有回头。虽然现在是 MSBuild 和 Cruise Control,但如果我需要做一些稍微涉及批处理脚本的事情,我会使用 jscript。

【讨论】:

  • 并不是这个问题的真正答案,但由于我已经去过 cmd.exe 字符串在批处理文件内外转义的 la-la-land,我完全同意你的看法。 +1
  • 不用说,这些天都是 Powershell。
  • @BinaryWorrier Mental,您肯定会与时俱进并使用 FAKE 吗? (实际上并不是在开玩笑,这很好)(免责声明:还没有 100% 确定您和/或 OP 正在谈论构建脚本 - 只是在跟踪者的基础上!)
【解决方案5】:

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 命令解释器中设置变量的好方法,但双引号方法更胜一筹:

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

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

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

因此,您将使用:

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

然而,即使变量被正确设置为这个字符串,当你 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>

【讨论】:

  • 您始终可以通过延迟扩展以安全的方式使用变量。 echo(!myvar! 输出不需要引号
【解决方案6】:

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

set myvar=c:\my music ^& videos

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

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

【讨论】:

    【解决方案7】:

    两种解决方案:

    1. 不要在路径名(目录名或文件名)中使用空格或其他对命令解释器来说是特殊的字符。如果您只使用字母、数字、下划线和连字符(以及在扩展名之前的一个句点来识别文件类型),您的脚本编写工作将变得无比简单。

      这些年来,我编写并收集了大量工具,包括用于重命名文件的 DOS 实用程序。 (它开始只是从文件名中删除空格,但演变成可以替换文件名中的字符或字符串的东西,甚至是递归的。)如果有人感兴趣,我会让我长期被忽视的网站启动并运行并发布这个和其他人。

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

    2. 正如其他人已经指出的那样,SET "myvar=c:\my music & videos" 是此类变量值的正确解决方法。 (是的,我说的是解决方法。我同意您最初倾向于仅引用值(“我的音乐和视频”)更直观,但正如他们所说的那样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      • 2010-12-23
      相关资源
      最近更新 更多