Windows 批处理-如何在变量之间传递多行字符串值

Windows 批处理-如何在变量之间传递多行字符串值,windows,batch-file,cmd,environment-variables,Windows,Batch File,Cmd,Environment Variables,问题是回声!出来显示除从指定的回显%data%之外的所有行!出来只显示第一行 @echo off call :f echo %data% :f setlocal EnableDelayedExpansion set out= set NL=^ for /f "delims=" %%i in ('dir /b') do ( if defined out set "out=!out!!NL!" set "out=!out!%%i" ) echo !out! set data=

问题是回声!出来显示除从指定的回显%data%之外的所有行!出来只显示第一行

@echo off

call :f
echo %data%

:f
setlocal EnableDelayedExpansion
set out=
set NL=^


for /f "delims=" %%i in ('dir /b') do (
    if defined out set "out=!out!!NL!"
    set "out=!out!%%i"
)
echo !out!
set data=!out!
exit /b 0
将值完全传递给我需要在endlocal之后自由使用的其他变量的正确方法是什么

感谢@aschipfl's的回答,澄清了如果不再次进入for循环是不可能做到的。实际上,我只想简化代码,而不必通过将其转换为子例程来多次编写for in循环。通过将子例程传递给子例程,我解决了这个问题。

从中派生,您不能使用立即展开来回送多行字符串,因为第一个换行符之后的所有内容都将被忽略

要使脚本正常工作,您需要纠正两个问题:

在行endlocal&set data=%out%之前,必须将变量out中的每一新行替换为转义新行,即序列^plus new line plus new line,该序列与定义变量NL时使用的序列完全相同; echo%data%在变量数据值中第一次出现新行时截断显示的字符串,因此您需要使用set data来显示变量的实际内容,或者更准确地说,显示名称以data开头的所有变量的实际内容; 以下代码中对这两项都进行了注释:

@回音 setlocal EnableDelayedExpansion 出发= 设置NL=^ 对于'dir/b'do中的/F delims=eol=|%%i 如果已定义,则设置=!出来NL! 出发!出去!%%我 echo*原始变量内容: 动身 rem//用转义新行替换每一新行: 出发!输出:^%NL%%NL%=^^^%NL%%NL%^%NL%%NL%^%NL%! echo*修改的变量内容: 动身 endlocal&设置数据=%out% rem//不要使用'echo'显示变量的真实内容: echo*返回的变量内容: 设置数据 echo*变量内容错误: 回显%数据% 退出/b0 虽然变量值现在已正确地传递到endlocal屏障上,但这种方法并不十分出色,因为它不允许您再次使用变量%data%,因为第一个换行符之后的所有内容都会被忽略,正如最初提到的,除非您在宿主cmd实例中启用了延迟扩展,这将允许使用!数据

另一个遗留问题是多行字符串中的特殊字符,如^、&、和|,可能会导致语法错误或其他意外问题。然而,这可以通过使用for元变量而不是普通环境变量来将变量值传递到endlocal屏障之外来避免,因为前者在特殊字符识别后展开,而后者在以下情况下展开:

@回音 setlocal EnableDelayedExpansion 出发= 设置NL=^ 对于/F delims=%%i在“dir/b”do中 如果已定义,则设置=!出来NL! 出发!出去!%%我 回显原始变量内容: 动身 rem/*使用`for`元变量而不是普通环境变量 rem将变量值传递到“endlocal”屏障之外; rem这里可以使用标准的'for'循环,因为不会有 rem通配符“?”和“*”在变量值中,因为它们已经 rem由'dir'解析`由于新行的原因,此处不能使用for/F`*/ 为了%%j英寸!出来do endlocal&设置数据=%%~j rem//不要使用'echo'显示变量的真实内容: echo返回的变量内容: 设置数据 回显变量内容: 回显%数据% 退出/b0 但是,无法使用变量%data%的问题仍然存在

然而,为了能够在即时扩展中使用变量%data%,您可以简单地在变量中存储转义新行,而不是文本行,因为在扩展时,您将获得预期的文本新行:

@回音 setlocal EnableDelayedExpansion 出发= 设置NL=^ 对于/F delims=%%i在“dir/b”do中 如果已定义,则设置=!出来NL! 出发!出去!%%我 回显原始变量内容: 动身 rem//用转义新行替换每一新行: 出发!输出:^%NL%%NL%=^^^%NL%%NL%^%NL%%NL%^%NL%! echo修改的变量内容: 动身 rem/*使用`for`元变量而不是普通环境变量 rem将变量值传递到“endlocal”屏障之外; rem这里可以使用标准的'for'循环,因为不会有 rem通配符“?”和“*”在变量值中,因为它们已经 rem由'dir'解析`由于新行的原因,此处不能使用for/F`*/ 为了%%j英寸!出来do endlocal&设置数据=%%~j rem//不要使用'echo'显示变量的真实内容: 回显实际变量内容: 设置数据 回显解析的变量内容: 回显%数据% 退出/b0
但请注意,只有当%data%未出现在带引号的字符串中时,此操作才会起作用。

通过禁用延迟扩展,可以完全避免此情况,尽管转义很复杂&out的内容将无法正确处理。看…我真的不知道你为什么
e创建了这个问题,但没有明确告诉读者您正在尝试创建一个变量,以保存Dir命令输出的全部内容。我的问题是,使用EndLocal的原因是什么?它所做的一切就是取消定义名为NL和out的变量,您可以简单地使用Set NL=和Set out=,或者在For循环之后立即对%%G In NL out Do Set%%G=执行此操作@对不起。我认为简化这个问题会更清楚。我已经编辑好了。谢谢你的回答。所以基本上我仍然需要使用for-in循环来完全复制这个值。很清楚