主要问题:
应如何更改已发布的批处理脚本combined.bat
,以使我可以同时在OUTPUT_A
和OUTPUT_B
上获得正确的输出? (必须具备EnableDelayedExpansion用法/范围的知识才能提供正确的解决方案)
上下文:
我结合了以下两个链接中的批处理脚本:
https://stackoverflow.com/a/15535761/7889588
https://helloacm.com/the-chr-function-implementation-in-windows-pure-batch-script/
并创建了以下批处理脚本(让我将其称为combined.bat
):
combined.bat
是一个ASCII Dec到ASCII Char转换器。
@echo off
@setlocal EnableDelayedExpansion
:: define characters from 32 to 126
set alphabet= !"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
set testVar=64_65_66_67_68_69_70_64
echo INPUT = %testVar%
echo.
set resultA=
call :CHR 64
set resultA=%resultA%%char%
call :CHR 65
set resultA=%resultA%%char%
call :CHR 66
set resultA=%resultA%%char%
call :CHR 67
set resultA=%resultA%%char%
call :CHR 68
set resultA=%resultA%%char%
call :CHR 69
set resultA=%resultA%%char%
call :CHR 70
set resultA=%resultA%%char%
call :CHR 64
set resultA=%resultA%%char%
echo OUTPUT_A = %resultA%
echo.
set char=randomValueJustToInitFill
call :split "%testVar%" "_" array
set resultB=
:: Loop through the resulting array
for /L %%I in (0, 1, %array.ubound%) do (
call :CHR !array[%%I]!
echo array[%%I] = !array[%%I]! = !char!
set resultB=!resultB!!char!
)
echo OUTPUT_B = !resultB!
echo.
goto :EOF
:CHR
:: valid range should be from 32 to 126 inclusive
if "%1"=="" goto :EOF
if %1 LSS 32 goto :EOF
if %1 GTR 126 goto :EOF
:: call function
call :ASCII %1 chr
:: print result, using ^ to escape special characters
:: such as <, > and |
REM echo.^%chr%
set char=^%chr%
:: end the script
goto :EOF
:: sub-routine
:ASCII
setlocal EnableDelayedExpansion
:: get the index
set /a var=%1-32
:: retrieve letter
set character=!alphabet:~%var%,1!
:: end the routine and return result as second parameter (out)
endlocal & set %2=^%character%
@EXIT /B 0
:: split subroutine
:split <string_to_split> <split_delimiter> <array_to_populate>
:: populates <array_to_populate>
:: creates arrayname.length (number of elements in array)
:: creates arrayname.ubound (upper index of array)
set "_data=%~1"
:: replace delimiter with " " and enclose in quotes
set _data="!_data:%~2=" "!"
:: remove empty "" (comment this out if you need to keep empty elements)
set "_data=%_data:""=%"
:: initialize array.length=0, array.ubound=-1
set /a "%~3.length=0, %~3.ubound=-1"
for %%I in (%_data%) do (
set "%~3[!%~3.length!]=%%~I"
set /a "%~3.length+=1, %~3.ubound+=1"
)
@EXIT /B 0
@endlocal
运行combined.bat
时,会产生以下内容:
INPUT = 64_65_66_67_68_69_70_64
OUTPUT_A = Z[\]_`aZ
array[0] = 64 = Z
array[1] = 65 = [
array[2] = 66 = \
array[3] = 67 = ]
array[4] = 68 = _
array[5] = 69 = `
array[6] = 70 = a
array[7] = 64 = Z
OUTPUT_B = Z[\]_`aZ
OUTPUT_A
和OUTPUT_B
都不正确。它偏移了26
。我有根据地猜测这是由2
,combined.bat
的第@setlocal EnableDelayedExpansion
行引起的。
因此,当我通过将行2
更改为REM @setlocal EnableDelayedExpansion
来注释掉行combined.bat
时,将产生以下内容:
INPUT = 64_65_66_67_68_69_70_64
OUTPUT_A = @ABCDEF@
array[0] = !array[0]! = !char!
array[1] = !array[1]! = !char!
OUTPUT_B = !resultB!
如您所见,OUTPUT_A
现在是正确的。但是,OUTPUT_B
的批处理代码无法正常工作。我尝试修改一下脚本(即将EnableDelayedExpansion
放在不同的位置,等等)。我仍然无法获得该脚本,无法在同一运行时为OUTPUT_A
和OUTPUT_B
产生正确的输出。
在提供解决方案时,请详细说明对combined.bat
所做的脚本更改。
答案 0 :(得分:0)
全部弄清楚,并发布了解决方案脚本以及脚本输出。
我更改了alphabet
,以使!
现在为^^!
,而^
现在为^^^
。这解决了大多数问题。但是,仍然存在一个错误,其中33
s无法正确转换为!
s。为了解决此问题,我必须对:CHR
和:ASCII
函数进行更改。这篇文章的底部列出了对该解决方案的重要脚本编辑。
解决方案-ASCII转换批处理脚本(已修复所有错误):
@echo off
@setlocal EnableDelayedExpansion
:: define characters from 32 to 126
set alphabet= ^^!"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^^_`abcdefghijklmnopqrstuvwxyz{|}~"
set testVar=64_65_66_67_68_69_70_64_32_33_34_126
echo INPUT = %testVar%
echo.
set resultA=
call :CHR 64
set resultA=!resultA!!char!
call :CHR 65
set resultA=!resultA!!char!
call :CHR 66
set resultA=!resultA!!char!
call :CHR 67
set resultA=!resultA!!char!
call :CHR 68
set resultA=!resultA!!char!
call :CHR 69
set resultA=!resultA!!char!
call :CHR 70
set resultA=!resultA!!char!
call :CHR 64
set resultA=!resultA!!char!
call :CHR 32
set resultA=!resultA!!char!
call :CHR 33
set resultA=!resultA!!char!
call :CHR 34
set resultA=!resultA!!char!
call :CHR 126
set resultA=!resultA!!char!
echo OUTPUT_A = !resultA!
echo.
set char=randomValueJustToInitFill
call :split "%testVar%" "_" array
set resultB=
:: Loop through the resulting array
for /L %%I in (0, 1, %array.ubound%) do (
call :CHR !array[%%I]!
echo array[%%I] = !array[%%I]! = !char!
set resultB=!resultB!!char!
)
echo OUTPUT_B = !resultB!
echo.
goto :EOF
:CHR
:: valid range should be from 32 to 126 inclusive
if "%1"=="" goto :EOF
if %1 LSS 32 goto :EOF
if %1 GTR 126 goto :EOF
:: call function
call :ASCII %1 chr
:: print result, using ^ to escape special characters
:: such as <, > and |
set char=!chr!
:: end the script
goto :EOF
:: sub-routine
:ASCII
:: get the index
set /a var=%1-32
:: retrieve letter
set character=!alphabet:~%var%,1!
:: end the routine and return result as second parameter (out)
set %2=!character!
@EXIT /B 0
:: split subroutine
:split <string_to_split> <split_delimiter> <array_to_populate>
:: populates <array_to_populate>
:: creates arrayname.length (number of elements in array)
:: creates arrayname.ubound (upper index of array)
set "_data=%~1"
:: replace delimiter with " " and enclose in quotes
set _data="!_data:%~2=" "!"
:: remove empty "" (comment this out if you need to keep empty elements)
set "_data=%_data:""=%"
:: initialize array.length=0, array.ubound=-1
set /a "%~3.length=0, %~3.ubound=-1"
for %%I in (%_data%) do (
set "%~3[!%~3.length!]=%%~I"
set /a "%~3.length+=1, %~3.ubound+=1"
)
@EXIT /B 0
@endlocal
解决方案脚本的输出:
INPUT = 64_65_66_67_68_69_70_64_32_33_34_126
OUTPUT_A = @ABCDEF@ !"~
array[0] = 64 = @
array[1] = 65 = A
array[2] = 66 = B
array[3] = 67 = C
array[4] = 68 = D
array[5] = 69 = E
array[6] = 70 = F
array[7] = 64 = @
array[8] = 32 =
array[9] = 33 = !
array[10] = 34 = "
array[11] = 126 = ~
OUTPUT_B = @ABCDEF@ !"~
更改为alphabet
变量:
以下内容解决了大部分问题。
已更改
set alphabet= !"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
到
set alphabet= ^^!"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^^_`abcdefghijklmnopqrstuvwxyz{|}~"
更改为:CHR
和:ASCII
功能:
以下内容修复了33
s无法正确转换为!
s的错误。
setlocal EnableDelayedExpansion
函数特有的本地endlocal &
和:ASCII
。set %2=!character!
代替set %2=^%character%
。set char=!chr!
代替set char=^%chr%
。