如果我写
setlocal EnableDelayedExpansion
for /L %%a in (1,1,%NUMBER%) do (
ECHO #define BLE_UUID_!SERVICE_NAME_UC!_!CARACTERISTIC_NAME_UC[%%a]!_CHAR !CARACTERISTIC_UUID[%%a]!
)
NUMBER , SERVICE_NAME_UC , CARACTERISTIC_NAME_UC [%% a] 和 CARACTERISTIC_UUID [%% a] 以前设置好了,一切正常,我得到了:
#define BLE_UUID_SECURITY_RELAY_CMD_CHAR 0x4800
#define BLE_UUID_SECURITY_RELAY_STATUS_CHAR 0x4801
#define BLE_UUID_SECURITY_CONFIG_CHAR 0x4802
但是,我想要做的是在执行任务的FOR循环中调用子例程,例如以这种方式:
setlocal EnableDelayedExpansion
for /L %%a in (1,1,%NUMBER%) do (
CALL :SetOutput_h %INPUT_HEADER_PATH%\DefCharUUID.txt %%a
)
GOTO:EOF
:SetOutput_h
:: Subroutine to insert parts of code in the header output file
:: The argument for this subroutine is the NAME of the code part you want to insert in the output file
SET "PART_NAME_H=%~1"
SET "INDEX=%~2"
(FOR /F "delims=" %%A IN ('findstr /N "^" %PART_NAME_H%') DO (
REM Get the line *including* !variable! replacements
SET "line=%%A"
REM Remove leading number, show the rest *including* empty lines
ECHO(!line:*:=!
)) >> %OUTPUT_H%
GOTO:EOF
文件 DefCharUUID.txt 只包含此内容:
#define BLE_UUID_!SERVICE_NAME_UC!_!CARACTERISTIC_NAME_UC[%INDEX%]!_CHAR !CARACTERISTIC_UUID[%INDEX%]!
genarated输出文件包含:
#define BLE_UUID_SECURITY__CHAR
因此,方括号的部分已被忽略。
我做错了什么?
答案 0 :(得分:0)
您的代码存在问题:
SET "line=%%A"
循环变量A
具有字符串值:
#define BLE_UUID_!SERVICE_NAME_UC!_!CARACTERISTIC_NAME_UC[%INDEX%]!_CHAR !CARACTERISTIC_UUID[%INDEX%]!
延迟扩展适用于将此字符串分配给环境变量line
。
但%INDEX%
的即时扩展不再进行了。 Windows命令解释器使用%VariableName%
扩展了所有环境变量引用,已经解析了整个 FOR 命令块,从代码开始(FOR /F
并以))
结束命令 FOR 是第一次执行。
因此,在将从文件读取的行分配给环境变量!SERVICE_NAME_UC!
时,SECURITY
被字符串line
替换。但Windows命令解释程序无法找到名为CARACTERISTIC_NAME_UC[%INDEX%]
的环境变量和另一个名为CARACTERISTIC_UUID[%INDEX%]
的环境变量,导致两个环境变量伪数组引用都被空字符串替换。
我不确定为什么你编写头文件创建这么复杂,但这里是你的问题的解决方案,其中包含额外的行minimal, complete, and verifiable example在批处理文件执行完成后不留任何文件。
@echo off
setlocal EnableExtensions
set "NUMBER=3"
set "SERVICE_NAME_UC=SECURITY"
set "CHARACTERISTIC_NAME_UC[1]=RELAY_CMD"
set "CHARACTERISTIC_NAME_UC[2]=RELAY_STATUS"
set "CHARACTERISTIC_NAME_UC[3]=CONFIG"
set "CHARACTERISTIC_UUID[1]=0x4800"
set "CHARACTERISTIC_UUID[2]=0x4801"
set "CHARACTERISTIC_UUID[3]=0x4802"
set "INPUT_HEADER_PATH=%TEMP%"
set "OUTPUT_H=%TEMP%\output.h"
del "%OUTPUT_H%" 2>nul
echo #define BLE_UUID_!SERVICE_NAME_UC!_!CHARACTERISTIC_NAME_UC[%%INDEX%%]!_CHAR !CHARACTERISTIC_UUID[%%INDEX%%]!>"%INPUT_HEADER_PATH%\DefCharUUID.txt"
for /L %%I in (1,1,%NUMBER%) do (
call :SetOutput_h "%INPUT_HEADER_PATH%\DefCharUUID.txt" %%I
)
type "%OUTPUT_H%"
del "%OUTPUT_H%"
del "%INPUT_HEADER_PATH%\DefCharUUID.txt"
endlocal
goto :EOF
:SetOutput_h
:: Subroutine to insert parts of code in the header output file.
:: The argument for this subroutine is the NAME of the code part you want to insert in the output file.
set "INDEX=%~2"
for /F "delims=" %%L in ('%SystemRoot%\System32\findstr.exe /N "^" "%~1"') do call :ExpandLine "%%L"
goto :EOF
:ExpandLine
set "Line=%~1"
call set "Line=%Line%"
setlocal EnableDelayedExpansion
set "Line=%Line%"
echo(!Line:*:=!>>"%OUTPUT_H%"
endlocal
goto :EOF
提供的解决方案将从文件读取的行传递给另一个子例程。传递的行首先分配给子例程Line
中的环境变量ExpandLine
。
使用命令行扩展使用立即扩展的下一个环境变量:
call set "Line=%Line%"
在此命令行之后,环境变量Line
首次运行主 FOR 时循环字符串值:
#define BLE_UUID_!SERVICE_NAME_UC!_!CHARACTERISTIC_NAME_UC[1]!_CHAR !CHARACTERISTIC_UUID[1]!
现在启用了延迟扩展,并且在将两次扩展行打印到输出文件之前,使用额外的延迟扩展再次扩展此行。
我非常确定您真正想要实现的目标可以更加轻松,如下所示,它完全省略了文件[%INDEX%]
中的DefCharUUID.txt
:
@echo off
setlocal EnableExtensions
set "NUMBER=3"
set "SERVICE_NAME_UC=SECURITY"
set "CHARACTERISTIC_NAME_UC[1]=RELAY_CMD"
set "CHARACTERISTIC_NAME_UC[2]=RELAY_STATUS"
set "CHARACTERISTIC_NAME_UC[3]=CONFIG"
set "CHARACTERISTIC_UUID[1]=0x4800"
set "CHARACTERISTIC_UUID[2]=0x4801"
set "CHARACTERISTIC_UUID[3]=0x4802"
set "INPUT_HEADER_PATH=%TEMP%"
set "OUTPUT_H=%TEMP%\output.h"
del "%OUTPUT_H%" 2>nul
echo #define BLE_UUID_!SERVICE_NAME_UC!_!CHARACTERISTIC_NAME_UC!_CHAR !CHARACTERISTIC_UUID!>"%INPUT_HEADER_PATH%\DefCharUUID.txt"
setlocal EnableDelayedExpansion
for /L %%I in (1,1,%NUMBER%) do (
set "CHARACTERISTIC_NAME_UC=!CHARACTERISTIC_NAME_UC[%%I]!"
set "CHARACTERISTIC_UUID=!CHARACTERISTIC_UUID[%%I]!"
for /F "delims=" %%L in ('%SystemRoot%\System32\findstr.exe /N "^" "%INPUT_HEADER_PATH%\DefCharUUID.txt"') do (
set "Line=%%L"
echo(!Line:*:=!>>"%OUTPUT_H%"
)
)
endlocal
type "%OUTPUT_H%"
del "%OUTPUT_H%"
del "%INPUT_HEADER_PATH%\DefCharUUID.txt"
endlocal
更多提示:
GOTO 是命令,:EOF
是参数。尽管Windows命令解释器在应用纠错后也处理GOTO:EOF
,但不要将它们一起编写。
建议在批处理文件中引用其他脚本或应用程序(如 FINDSTR )以及完整路径和文件扩展名,以使批处理文件独立于本地环境变量PATHEXT
的当前值和PATH
尽可能多。
将所有文件/目录引用用双引号括起来,即使当前文件/目录名称/路径并不真正需要,因为将来真正了解文件/目录名称/路径。