Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file 如何将参数批量传递给作用于外部文件的子例程_Batch File_Parameters_Subroutine - Fatal编程技术网

Batch file 如何将参数批量传递给作用于外部文件的子例程

Batch file 如何将参数批量传递给作用于外部文件的子例程,batch-file,parameters,subroutine,Batch File,Parameters,Subroutine,如果我写 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]! ) 如果之前已经设置了编号、服务名称、特征名称和特征ID,则一切正常,我获得: #define BLE_UUID_SECURITY_RELAY_

如果我写

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]!
)
如果之前已经设置了编号、服务名称、特征名称和特征ID,则一切正常,我获得:

#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%]!
#define BLE_UUID_SECURITY__CHAR
输出文件包含以下内容:

#define BLE_UUID_!SERVICE_NAME_UC!_!CARACTERISTIC_NAME_UC[%INDEX%]!_CHAR    !CARACTERISTIC_UUID[%INDEX%]!
#define BLE_UUID_SECURITY__CHAR
因此,方括号中的部分已被忽略


我做错了什么?

代码的问题在于行:

SET "line=%%A"
循环变量
A
具有字符串值:

#define BLE_UUID_!SERVICE_NAME_UC!_!CARACTERISTIC_NAME_UC[%INDEX%]!_CHAR    !CARACTERISTIC_UUID[%INDEX%]!
#define BLE_UUID_!SERVICE_NAME_UC!_!CHARACTERISTIC_NAME_UC[1]!_CHAR    !CHARACTERISTIC_UUID[1]!
延迟扩展应用于将此字符串分配给环境变量

但是,
%INDEX%
的即时扩展不再进行。Windows命令解释器扩展了所有环境变量引用,使用已在解析整个FOR命令块时使用的
%VariableName%
,该命令块在代码中以
开头(FOR/F
,以
结尾)
在首次执行FOR命令之前

因此,
!服务\u名称\u UCline
时,code>将替换为字符串
SECURITY
。但是Windows命令解释器无法找到名为
CARACTERISTIC\u name\u UC[%INDEX%]
的环境变量和名为
CARACTERISTIC\u UUID[%INDEX%]
的另一个环境变量,导致两个环境变量伪数组引用都被空字符串替换

我不知道为什么要将头文件的创建编码得如此复杂,但这里有一个解决方案,它包含了额外的行,用于在批处理文件执行完成后不留下任何文件

@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
提供的解决方案将从文件读取的行传递给另一个子例程。传递的行首先分配给子例程
ExpandLine
中的环境变量
line

接下来,使用立即展开的环境变量将使用命令行展开:

call set "Line=%Line%"
在此命令行之后,环境变量
line
在第一次运行mainFOR循环时具有字符串值:

#define BLE_UUID_!SERVICE_NAME_UC!_!CARACTERISTIC_NAME_UC[%INDEX%]!_CHAR    !CARACTERISTIC_UUID[%INDEX%]!
#define BLE_UUID_!SERVICE_NAME_UC!_!CHARACTERISTIC_NAME_UC[1]!_CHAR    !CHARACTERISTIC_UUID[1]!
现在,延迟扩展已启用,并且在将两次扩展的行打印到输出文件之前,使用额外的延迟扩展再次扩展此行

我非常确信,您真正想要实现的目标可以更容易地实现,如下所示,它完全省略了文件
DefCharUUID.txt中的
[%INDEX%]

@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
的当前值


将所有文件/目录引用用双引号括起来,即使不需要使用当前文件/目录名称/路径,因为谁真正知道将来的文件/目录名称/路径。

为什么要
调用
ing
:使用两个参数设置output\u h
,其中第一个参数对for循环完全是多余的?如果在该循环之前
设置“PART\u NAME\u H=%INPUT\u HEADER\u PATH%\DefCharUUID.txt”
,则只
调用:SetOutput\u H%%a
设置“INDEX=%1”
,尽管我还注意到您似乎也没有使用
%INDEX%