我面临的限制是我只能使用 CMD(由于项目的设置)。 CMD 的问题在于
for /f "tokens...
总是会逐行解析 set
的结果。这意味着具有多行值的环境变量将被解析为 2 个标记。
示例:
for /f "tokens=1* delims==" %%a in ('set') do (
将在 2 个单独的迭代中解析多行环境变量,因此您无法替换换行符。
尝试过类似的事情:
REM Loop through the environment variables
for /f "tokens=1* delims==" %%a in ('set') do (
REM Replace newline characters with spaces
set "value=%%b"
set "value=!value:^
...
但没有成功
转载者: 示例:
C:\Users\so>set NL=^
More?
More? test
C:\Users\so>set
LOGONSERVER=\\so
--other values--
NL=
test
NUMBER_OF_PROCESSORS=20
如果你知道变量名称,那就很简单了
@echo off
setlocal
REM *** Prepare test variable
set test_var=Line1^
Line2
echo Original:
set "test_var"
echo(
call :sanitize test_var
exit /b
:sanitize
setlocal EnableDelayedExpansion
(set LF=^
%=empty=%
)
FOR /F "delims=" %%V in ("%1") DO set "tmp=!%%V!"
FOR %%L in ("!LF!") DO set "sanitized=!tmp:%%~L=-LF-!"
echo Sanitized: !sanitized!
endlocal
exit /b
如果使用
SET
命令列出变量
那就很棘手了,因为你无法知道一行是否以变量名开头或多行变量的内容,这可能与有效的变量定义相同。
示例
设置测试
测试1=第1行
测试2=第2行
这可以解释为两个变量
test1
和 test2
,也可以只是一个变量 test1,内容为 Line1\ntest=Line2
因此你需要一个更复杂的解决方案
@echo off
setlocal
REM *** Prepare test variable
set test1=Line1^
Line2
set test3=Line3
call :sanitize_all
exit /b
:sanitize_all
setlocal EnableDelayedExpansion
(set LF=^
%=empty=%
)
set "tmp=!var!"
setlocal DisableDelayedExpansion
set "ignoreLines=0"
FOR /F "tokens=1 delims==" %%V in ('SET test') DO (
set /a 1/ignoreLines 2> NUL
if errorlevel 1 (
call :sanitize
) else (
set /a ignoreLines-=1
)
)
endlocal
exit /b
:sanitize
setlocal EnableDelayedExpansion
(set LF=^
%=empty=%
)
FOR /F "delims=" %%X in ("dummy") DO (
set "varName=%%V"
set "tmp=!%%V!"
)
FOR %%L in ("!LF!") DO set "sanitized=!tmp:%%~L=-LF-!"
REM *** This works only for a single LF in a variable
if "!tmp!" NEQ "!sanitized!" set "ignoreLines=1"
echo Sanitized: !varName!=!sanitized!
(
endlocal
set "ignoreLines=%ignoreLines%"
)
exit /b