jenkins 在两个几乎相同的批处理脚本之一中出现错误:“)”不能在此处按语法处理

nuypyhwy  于 2023-10-17  发布在  Jenkins
关注(0)|答案(1)|浏览(129)

我正在尝试为自动Unity构建设置Jenkins服务器。
因此,我写了两个(在我看来)基本相同的批处理脚本。
这两个脚本都是由Jenkins通过Execute Windows batch command步骤作为构建步骤运行的,

命令:E:\unityImport.bat

并且在此之后,第二Execute Windows batch command步骤使用

命令:E:\unityBuild.bat

他们都有相同的开始,因为我需要收集一些文件路径,特别是项目的统一版本。因此,在这两个脚本中,我使用完全相同的方式解析和字符串拆分项目版本。它们之间唯一不同的是,第一个启动Unity并将专用的unitypackage(其中包含下一步要执行的方法)导入到项目中,而第二个再次启动Unity以执行实际的构建(不幸的是,它并没有一次完成)。Unity似乎试图在导入unitypackage之前执行该方法)。
但是,第二个脚本总是失败,并出现语法错误
“)”不能在此处按语法处理。
我想做的是
1.读取文件%WORKSPACE%\ProjectSettings\ProjectVersion.txt的内容

SET /p TEST=<%WORKSPACE%\ProjectSettings\ProjectVersion.txt

%TEST%的内容通常看起来像这样。

m_EditorVersion: 2019.3.4f1

ECHO. ProjectVersion.txt = %TEST%看起来像

ProjectVersion.txt = m_EditorVersion: 2019.3.4f1

1.拆分字符串,以便只取包含版本号的最后一部分

for %%x in (%TEST::= %) do (
    SET "VALUE=%%x"
    SET "UNITY_VERSION=!VALUE:~0,-2!" 
)

所以%UNITY_VERSION%通常包含例如2019.3.4。我不分开更多的,因为也有统一的版本与两位数,如。2018.4.18
1.在.上拆分字符串,以便仅获取主版本号

for /f "tokens=1,2 delims=." %%a in ("%UNITY_VERSION%") do (
    SET "A=%%a"
    SET "B=%%b"
)
SET "UNITY_VERSION=%A%.%B%"

这导致%UNITY_VERSION%例如是2019.3
1.最后搜索所有已安装的Unity版本(如果存在所需版本)

set "UNITY_FOLDER="
for /f "delims=" %%a in ('dir /b E:\Unity\%UNITY_VERSION%*') do (
    set "UNITY_FOLDER=%%a"
)

在此之后,我们要么找到了给定版本的有效Unity安装文件夹,要么没有。
这是剧本。

导入(按预期工作)

@ECHO OFF
CLS
ECHO.

cd %WORKSPACE%

IF NOT EXIST %WORKSPACE%\ProjectSettings\ProjectVersion.txt (
    EXIT 1
)

SETLOCAL ENABLEDELAYEDEXPANSION

SET /p TEST=<%WORKSPACE%\ProjectSettings\ProjectVersion.txt
ECHO. ProjectVersion.txt = %TEST%

for %%x in (%TEST::= %) do (
    SET "VALUE=%%x"
    SET "UNITY_VERSION=!VALUE:~0,-2!" 
)

for /f "tokens=1,2 delims=." %%a in ("%UNITY_VERSION%") do (
    SET "A=%%a"
    SET "B=%%b"
)

SET "UNITY_VERSION=%A%.%B%"
ECHO. Project Unity Version = %UNITY_VERSION%

set "UNITY_FOLDER="
for /f "delims=" %%a in ('dir /b E:\Unity\%UNITY_VERSION%*') do (
    set "UNITY_FOLDER=%%a"
)

IF "%UNITY_FOLDER%"=="" (
    EXIT 1
)

ECHO. Using Unity Version %UNITY_FOLDER%

ECHO. Running:
ECHO. E:\Unity\%UNITY_FOLDER%\Editor\Unity.exe -quit -batchmode -projectPath %WORKSPACE% -logFile - -importPackage E:\UnityBuildPackage\AutoBuilder.unitypackage

E:\Unity\%UNITY_FOLDER%\Editor\Unity.exe -quit -batchmode -projectPath %WORKSPACE% -logFile - -importPackage E:\UnityBuildPackage\AutoBuilder.unitypackage

IF NOT %errorlevel% equ 0 (
    EXIT 1
) 

EXIT 0

Build(这会失败,因为语法错误,我会用REM HERE IT BREAKS! ...标记,实际脚本中不存在)

@ECHO OFF
CLS
ECHO.

cd %WORKSPACE%

IF NOT EXIST %WORKSPACE%\ProjectSettings\ProjectVersion.txt (
    EXIT 1
)

SETLOCAL ENABLEDELAYEDEXPANSION

SET /p TEST=<%WORKSPACE%\ProjectSettings\ProjectVersion.txt
ECHO. ProjectVersion.txt = %TEST%

REM HERE IT BREAKS! The before echo is the last I see before getting the syntax error

for %%x in (%TEST::= %) do (
    SET "VALUE=%%x"
    SET "UNITY_VERSION=!VALUE:~0,-2!" 
)

for /f "tokens=1,2 delims=." %%a in ("%UNITY_VERSION%") do (
    SET "A=%%a"
    SET "B=%%b"
)

SET "UNITY_VERSION=%A%.%B%"
ECHO. Project Unity Version = %UNITY_VERSION%

set "UNITY_FOLDER="
for /f "delims=" %%a in ('dir /b E:\Unity\%UNITY_VERSION%*') do (
    set "UNITY_FOLDER=%%a"
)

IF "%UNITY_FOLDER%"=="" (
    EXIT 1
)

ECHO. Using Unity Version %UNITY_FOLDER%

...

我不认为其余的问题,因为正如所说,我在控制台看到它已经打破后,例如。
ProjectVersion.txt = 2019.3.4f1
“)”不能在此处按语法处理。

有没有人看到这个错误,或者Jenkins可能有什么东西导致第二个脚本失败,并出现语法错误,尽管据我所知,它们基本上是相同的?

ogq8wdun

ogq8wdun1#

代码中有多个小问题,我会在我对批处理文件的建议下面逐一解释。
根据文件ProjectVersion.txt中定义的UNITY_VERSION获取UNITY_FOLDER的任务可以通过使用以下代码更有效地完成:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

if not defined WORKSPACE (
    echo ERROR: Environment variable WORKSPACE is not defined.
    exit /B 1
)

if not exist "%WORKSPACE%\ProjectSettings\ProjectVersion.txt" (
    echo ERROR: File "%WORKSPACE%\ProjectSettings\ProjectVersion.txt" does not exist.
    exit /B 1
)

set "UNITY_FOLDER="
set "UNITY_VERSION="
for /F "usebackq tokens=2-4 delims=. " %%I in ("%WORKSPACE%\ProjectSettings\ProjectVersion.txt") do (
    if not "%%~K" == "" (
        for /F "delims=abcdef" %%L in ("%%~K") do (
            set "UNITY_VERSION=%%~I.%%~J.%%~L"
            for /D %%M in ("E:\Unity\%%~I.%%~J*") do set "UNITY_FOLDER=%%M"
        )
    )
)

if not defined UNITY_VERSION (
    echo ERROR: Failed to determine unity version from "%WORKSPACE%\ProjectSettings\ProjectVersion.txt".
    exit /B 1
)
if not defined UNITY_FOLDER (
    echo ERROR: Failed to find a folder in "E:\Unity" for unity version %UNITY_VERSION%.
    exit /B 1
)

echo Found for unity version %UNITY_VERSION% the folder "%UNITY_FOLDER%".

cd /D "%WORKSPACE%" 2>nul
if errorlevel 1 (
    echo ERROR: Failed to set "%WORKSPACE%" as current folder.
    exit /B
)
rem Other commands to execute.

endlocal

此批处理文件首先使用命令SETTABLE设置此批处理文件所需的执行环境。
接下来通过批处理文件验证环境变量WORKSPACE的存在。这个环境变量应该由Jenkins在这个批处理文件之外定义。如果缺少此重要环境变量的定义,则会输出错误消息。
然后检查文本文件是否存在,如果不存在则打印错误消息,并使用退出代码1退出批处理文件。
如果在批处理文件外部偶然定义了两个环境变量UNITY_FOLDERUNITY_VERSION,则会将其删除。
接下来,处理文本文件,该文件应该只包含一个包含感兴趣数据的非空行。否则,在执行其他命令之前,如果第一个子字符串等于m_EditorVersion:,则需要更改代码以评估第一个子字符串。
带有/F选项的FOR默认将"中包含的集合解释为要处理的字符串。但在这种情况下,"中的字符串应被解释为文件的完整限定文件名,其内容应逐行处理FOR。因此,选项usebackq用于获取所需的文件内容处理行为。

FOR在处理文件内容时忽略始终为空行。因此,如果文本文件在顶部包含一个或多个空行,则没有关系。

默认情况下,FOR使用普通空格和水平制表符作为字符串分隔符将一行拆分为子字符串。如果第一个空格/制表符分隔的字符串在删除所有前导空格/制表符后以一个默认的行尾字符开始,那么该行也会被FOR忽略,就像一个空行一样。最后,第一个空格/制表符分隔的字符串将被分配给指定的循环变量I
这里不需要这种默认的行处理行为,因为仅仅将m_EditorVersion:赋给指定的循环变量I是不够的。出于这个原因,选项delims=. 用于将行拆分为点和空格。选项tokens=2-4通知FOR第二个空格/点分隔的子字符串2019应该分配给循环变量I,第三个空格/点分隔的子字符串3到下一个循环变量J,它是ASCII table中的下一个字符,第四个空格/点分隔子串4f1到下一个循环变量K
这里重要的是在选项参数字符串的末尾指定delims=. ,并将空格字符作为最后一个字符,因为空格字符会被解释为选项分隔字符,例如usebackqtokens=2-4之间的空格以及tokens=2-4delims=. 之间的空格。事实上,也可以编写没有空格的选项,如"usebackqtokens=2-4delims=. ",但这会使带有选项的参数字符串难以阅读。
默认的行结束定义eol=;可以保留在这里,因为在ProjectVersion.txt中具有unity版本的行在0或更多的空格/点之后没有一个空格,并且永远不会因为这个原因而被忽略。

FOR运行命令块中的命令,在行中找到至少第二个分配给循环变量I的空格/点分隔字符串,即将非空字符串分配给指定的循环变量I。但是,只有当统一版本的所有三个部分都由FOR确定并分配给循环变量IJK时,才应该执行命令。因此,进行一个简单的字符串比较,以验证循环变量值引用%%~K没有扩展为空字符串,因为这意味着没有从文件中读取足够的统一版本部分。

我不知道编辑器版本末尾的f1是什么意思。因此,再使用一个带有/F选项的FORstring4f1"中包含的字符串上没有usebackq)拆分为子字符串,使用字符abcdef(小写十六进制字符)作为字符串分隔符,并将指定的循环变量L仅分配给第一个子字符串。这应该永远不会失败,因此环境变量UNITY_VERSION被定义为2019.3.4
第三个FOR在第二个FOR内部执行,尽管它也可以在外部执行,因为没有引用循环变量L。所以下面的代码也可以用在这里,得到同样的结果。

for /F "usebackq tokens=2-4 delims=. " %%I in ("%WORKSPACE%\ProjectSettings\ProjectVersion.txt") do (
    if not "%%~K" == "" (
        for /F "delims=abcdef" %%L in ("%%~K") do set "UNITY_VERSION=%%~I.%%~J.%%~L"
        for /D %%M in ("E:\Unity\%%~I.%%~J*") do set "UNITY_FOLDER=%%M"
    )
)

FOR带有选项/D和包含*(或?)的集合将导致在指定目录E:\Unity中搜索名称以2019.3开头的非隐藏目录。E:\Unity中每个与2019.3*匹配的非隐藏目录都被一个接一个地分配了完整的限定名(驱动器+路径+名称),首先分配给循环变量M,然后分配给环境变量UNITY_FOLDERFOR从不在"中包含文件/文件夹字符串,这就是为什么%%M可以在这里使用,而%%~M是不必要的。在这种情况下,分配给循环变量M的文件夹名称永远不会包含在"中。因此,环境变量UNITY_FOLDER包含最后一个文件夹,该文件夹与文件系统返回的具有完整路径的模式相匹配。这意味着在多个文件夹名称与2019.3*匹配时,文件系统将确定最后分配给UNITY_FOLDER的文件夹名称。NTFS将目录项存储在其主文件表中,并按本地特定的字母顺序排序,而FAT、FAT32和exFAT则将目录项存储在其文件分配表中,但不进行排序。
**注意:**如果第三个编辑器版本号不是真正需要的,因为它看起来像根据问题的代码,也可以使用:用途:

for /F "usebackq tokens=2-4 delims=. " %%I in ("%WORKSPACE%\ProjectSettings\ProjectVersion.txt") do (
    if not "%%~J" == "" (
        set "UNITY_VERSION=%%~I.%%~J"
        for /D %%K in ("E:\Unity\%%~I.%%~J*") do set "UNITY_FOLDER=%%K"
    )
)

如果代码可以成功确定unity版本并找到匹配的unity文件夹,则进行两次额外检查。
批处理文件底部的echo命令行只是为了验证在命令提示符窗口中使用批处理文件外部定义的WORKSPACE运行此批处理文件的结果,并且一切都按预期工作。
不需要将工作区目录设置为批处理文件末尾的当前目录,但是我添加了代码来验证是否成功地将当前目录更改为工作区目录。

第1期:文件/文件夹参数字符串未用引号括起来

command promptcmd /?中运行的帮助输出在最后一页的最后一段解释了包含空格或其中一个字符&()[]{}^=;!'+,~的文件/文件夹参数字符串需要用双引号括起来。因此,建议始终在"`中包含不带路径或带路径的文件/文件夹名称,特别是由环境变量动态定义或从文件系统读取的一个或多个部分。
下面的命令行不太好:

cd %WORKSPACE%
IF NOT EXIST %WORKSPACE%\ProjectSettings\ProjectVersion.txt
SET /p TEST=<%WORKSPACE%\ProjectSettings\ProjectVersion.txt

最好使用:

cd "%WORKSPACE%"
IF NOT EXIST "%WORKSPACE%\ProjectSettings\ProjectVersion.txt"
SET /p TEST=<"%WORKSPACE%\ProjectSettings\ProjectVersion.txt"

在运行cd /?的简短帮助输出中可以看到,命令CD不会将空格字符解释为参数分隔符,就像Windows命令处理器cmd.exe的大多数其他内部命令或目录%SystemRoot%\System32中的可执行文件一样,这些命令默认安装并且根据Microsoft也属于Windows commands。但是,如果目录路径偶然包含一个与号,则更改当前目录会失败,因为cmd.exe在执行CD之前已经将&外部的双引号参数字符串解释为AND运算符,例如我在single line with multiple commands上的回答中所描述的。
最好在每个可能包含空格或&()[]{}^=;!'+,~或重定向操作符<>|的参数字符串上使用包围",这些操作符应被Windows命令处理器解释为参数字符串的文字字符。好吧,方括号对Windows命令处理器不再有特殊意义。[]在列表中是由于历史原因,因为MS-DOS的第一个版本的COMMAND.COM`并不总是将它们解释为文字字符。

第2期:单个命令的命令块用法

Windows命令处理器主要用于

  • 打开批处理文件,
  • 阅读批处理文件中从先前记忆的字节偏移量或第一行上的偏移量0开始的行,
  • 解析和预处理这一行,
  • 关闭批处理文件,不再读取行,
  • 在批处理文件中存储当前字节偏移量,
  • 执行命令行。

运行if /?时命令IF的帮助输出在第一页的顶部显示了在条件为true时执行的命令与命令IF位于同一行的常规语法。运行for /?时命令FOR的帮助输出在第一页的顶部显示了在每次循环迭代中执行的命令与命令FOR位于同一行的常规语法。因此,此推荐语法应用于只需要执行一个命令的IF条件和FOR循环。
让我们看看Windows命令处理器如何解释以下IF条件,其中环境变量WORKSPACE是用C:\Temp定义的:

IF NOT EXIST %WORKSPACE%\ProjectSettings\ProjectVersion.txt (
    EXIT 1
)

只有这三行的批处理文件将导致执行:

IF NOT EXIST C:\Temp\ProjectSettings\ProjectVersion.txt (EXIT 1 )

因此,Windows命令处理器检测到有一个以(开头的命令块,从批处理文件中读取更多行,直到匹配),发现命令块仅由一个命令行组成,并因此将三行合并到一个命令行中。
因此,批处理文件处理可以通过在批处理文件中写入来加快一点点:

IF NOT EXIST "%WORKSPACE%\ProjectSettings\ProjectVersion.txt" EXIT /B 1

然后,cmd.exe需要更少的CPU指令来执行。

IF NOT EXIST "C:\Temp\ProjectSettings\ProjectVersion.txt" EXIT /B 1

然而,使用命令块总是可以使批处理文件的代码更好地可读。
如果可以避免对批处理文件执行大量的文件打开、读取和关闭操作,甚至可以将经常执行的批处理文件的整个代码或部分代码放在一个命令块中,这些操作有时会对总执行时间产生巨大影响,如Why is a GOTO loop much slower than a FOR loop and depends additionally on power supply?所示。
参见How does the Windows Command Interpreter (CMD.EXE) parse scripts?

第三期:ECHO.可能导致不必要的行为

DosTips论坛主题ECHO. FAILS to give text or blank line - Instead use ECHO/解释了ECHO.可能无法输出文本或空行。如果下一个字符不是?,则使用ECHO/更好,最好是ECHO(
如果保证在ECHO 之后有文本要输出,则将命令ECHO与要输出的字符串分隔的字符可以是标准参数分隔符空格。
ECHO/可以输出一个空行。
ECHO(是最好的,如果有下一个环境变量引用或循环变量引用,在此之前没有确定环境变量是否定义,或者循环变量存在非空字符串,而不是以问号开头。

第四期:使用SET /P从文本文件中读取一行

可以使用set /P从文本文件中读取第一行,并将该行分配给环境变量,如下所示:

SET /p TEST=<%WORKSPACE%\ProjectSettings\ProjectVersion.txt

但是文本文件必须在文件顶部有要分配给环境变量的文本。文本文件顶部的一个空行会导致环境变量没有任何赋值,这意味着如果环境变量TEST已经定义,则其值根本不会改变,如果环境变量TEST之前没有定义,则执行SET后仍然没有定义。
最好使用带有/F选项的命令FOR来处理文本文件的内容。

第五期:使用不带选项/B的EXIT命令

命令EXIT退出正在处理批处理文件的Windows命令进程。它总是有效的,但是在大多数批处理文件中应该避免使用不带/B选项的EXIT
如果cmd.exe在批处理文件上执行EXIT(不带/B,不带退出代码或带退出代码),则cmd.exe始终会自行终止,即使在cmd.exe上隐式或显式启动,并使用选项/K在完成命令执行后保持命令进程运行,命令行或批处理文件,并且独立于批处理文件调用层次。
一个批处理文件EXIT没有选项/B因此很难debug,因为即使在运行批处理文件从命令提示符窗口,而不是双击它看到错误消息,命令进程和控制台窗口关闭cmd.exe到达命令行与EXIT

第六期:批处理文件取决于外部定义的环境

设计良好的批处理文件不依赖于在批处理文件外部定义的执行环境。这两个批处理文件使用的命令的功能仅在启用命令扩展名时可用。默认情况下,命令扩展是启用的,延迟环境变量扩展是禁用的,但是当批处理文件将自己定义为执行环境并在退出之前恢复以前的执行环境时,情况会更好。这样可以确保批处理文件始终按设计工作,即使调用此批处理文件的另一个批处理文件设置了不同的执行环境。
因此,在@echo off之后,为了确保关闭ECHO模式,下一个命令行应该是:

setlocal EnableExtensions DisableDelayedExpansion

那么批处理文件肯定会在预期的环境中执行。命令endlocal应位于批处理文件的末尾,以恢复初始执行环境。但是Windows命令处理器在退出批处理文件处理之前隐式地运行endlocal,对于每个执行的setlocal,在退出批处理文件处理之前没有执行匹配的endlocal
执行setlocal /?endlocal /?会显示这两个命令的帮助。在this answer中可以找到一个更好的解释,其中包含有关命令SETSTACKENDSTACK的更多细节。

在批处理文件的顶部使用setlocal来设置所需的执行环境,在批处理文件的底部使用endlocal来恢复初始执行环境,必须明智地进行,以防批处理文件通过环境变量将结果返回到初始执行环境,如调用当前执行的批处理文件的父批处理文件。

第七期:使用字母ADFNPSTXZadfnpstxz作为循环变量

运行for /?时命令FOR输出的帮助描述了可用于引用循环变量值的修饰符。

%~I         - expands %I removing any surrounding quotes (")
   %~fI        - expands %I to a fully qualified path name
   %~dI        - expands %I to a drive letter only
   %~pI        - expands %I to a path only
   %~nI        - expands %I to a file name only
   %~xI        - expands %I to a file extension only
   %~sI        - expanded path contains short names only
   %~aI        - expands %I to file attributes of file
   %~tI        - expands %I to date/time of file
   %~zI        - expands %I to size of file
   %~$PATH:I   - searches the directories listed in the PATH
                  environment variable and expands %I to the
                  fully qualified name of the first one found.
                  If the environment variable name is not
                  defined or the file is not found by the
                  search, then this modifier expands to the
                  empty string

可以组合这些修改器以获得复合结果:

%~dpI       - expands %I to a drive letter and path only
   %~nxI       - expands %I to a file name and extension only
   %~fsI       - expands %I to a full path name with short names only
   %~dp$PATH:I - searches the directories listed in the PATH
                  environment variable for %I and expands to the
                  drive letter and path of the first one found.
   %~ftzaI     - expands %I to a DIR like output line

修饰符被解释为不区分大小写,这意味着%~FI%~fI相同,而循环变量被解释为始终区分大小写,这意味着循环变量I被解释为与循环变量i不同。
建议避免将字母ADFNPSTXZadfnpstxz作为循环变量,尽管这些字母也可以用作循环变量,特别是如果循环变量引用与下面的批处理文件命令行示例中的字符串连接。

for %%x in ("1" 2,3;4) do echo %%~xx5 = ?

直接在命令提示符窗口中执行的相同示例:

for %x in ("1" 2,3;4) do @echo %~xx5 = ?

输出通常是(不总是):

5 = ?
5 = ?
5 = ?
5 = ?

但是在批处理文件中使用I的输出更有意义:

for %%I in ("1" 2,3;4) do echo %%~Ix5 = ?

直接在命令提示符窗口中执行的相同命令行:

for %I in ("1" 2,3;4) do @echo %~Ix5 = ?

在这种情况下,输出总是:

1x5 = ?
2x5 = ?
3x5 = ?
4x5 = ?

因此,在以下情况下,不可能使用ADFNPSTXZadfnpstxz作为循环变量:
1.循环变量值是用一个修饰符引用的,这意味着循环变量值引用以%~(命令提示符窗口)或%%~(批处理文件)开头,
1.循环变量值引用与第一个字符与用于循环变量的字母相同的字符串连接。
所以在命令提示符窗口中工作良好的是:

for %x in (1 2,3;4) do @echo %xx5 = ?      & rem Condition 1 is not true.
for %n in ("1" 2,3;4) do @echo %~nx5 = ?   & rem Condition 2 is not true.
for %x in ("1" 2,3;4) do @echo %~x+5 = ?   & rem Condition 2 is not true.

然而,使用一个字母来引用赋给带有修饰符的循环变量的字符串值,可读性不好。
在命令提示符窗口中使用的可读性示例:

for %i in (*) do @echo %~si
for %f in (*) do @echo %~sf
for %i in (*) do @echo %~sni
for %f in (*) do @echo %~snf

在这种情况下,if都可以工作,输出是相同的,与if的使用无关。但是,使用i而不是f作为循环变量时,更容易看到修改器(sn)以及循环变量。
也可以使用其他ASCII字符而不是对Windows命令处理器没有特殊意义的字母,如#作为循环变量,如果不使用带有选项/FFOR,其中多个子字符串被分配给多个循环变量。

第八期:用FOR处理不带通配符的集合

让我们看看使用下面的代码实际上发生了什么:

setlocal EnableExtensions EnableDelayedExpansion
set "TEST=m_EditorVersion: 2019.3.4f1"
for %%x in (%TEST::= %) do (
    SET "VALUE=%%x"
    SET "UNITY_VERSION=!VALUE:~0,-2!" 
)
endlocal

字符串替换%TEST::= %会导致在使用命令块解析FOR命令行时,将分配给环境变量TEST的字符串中的每个冒号替换为空格。所以绳子

m_EditorVersion: 2019.3.4f1

成为

m_EditorVersion  2019.3.4f1

接下来,Windows命令处理器将m_EditorVersion2019.3.4f1之间的两个空格替换为单个空格作为清理。因此,for处理的set最终是在使用for及其命令块解析和预处理命令行之后:

m_EditorVersion 2019.3.4f1

这个集合既不包含*也不包含?。出于这个原因,命令FOR将set解释为两个简单的空格分隔字符串,依次分配给指定的循环变量x,并为这两个字符串执行命令块中的命令两次。
在第一次迭代中,m_EditorVersion被分配给环境变量VALUEm_EditorVersi被分配给环境变量UNITY_VERSION。这并不是真正想要的,但是FOR再次运行这两个命令,这次将2019.3.4f1赋值给循环变量x。因此,在第二次循环迭代中,2019.3.4f1被分配给环境变量VALUE2019.3.4被分配给环境变量UNITY_VERSION
UNITY_VERSION最后是用想要的字符串定义的,但是可以做得更好,如这个答案顶部所示和解释的那样。
我不太清楚为什么for命令行会导致错误消息:
“)”不能在此处按语法处理。
对于m_EditorVersion: 2019.3.4f1上的这个FOR循环来说,这不应该发生,因为它被分配给了环境变量TEST
要么TEST是用一个字符串定义的,导致在执行第二个批处理文件时出现语法错误,尽管根据描述不应该是这种情况,要么(被解释为命令块的开始,Windows命令处理器无法找到标记命令块结束的匹配)

相关问题