我有如下代码:
FOR /F "tokens=*" %%B IN ('%*') DO (
ECHO %%B
SET data=%%B
ECHO %data%
)
%% B包含一个或多个|字符,例如%% B的值是 First |第二|第三。 SET data = %% B 或 SET data =“ %% B” 功能不起作用。回叫%data%时,它表明Echo已关闭。
我需要删除| %% B中的字符并将其保存到%data%变量中。但是我不知道怎么办?
如果有人提供任何解决方案,我将不胜感激。
答案 0 :(得分:2)
第一个解决方案是使用:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
for /F delims^=^ eol^= %%B in ('%*') do (
set "data=%%B"
set "data=!data:|=!"
echo(!data!
)
endlocal
tokens=*
导致将整个行分配给循环变量B
,并且删除前导空格/制表符,而delims=
导致将分配给整个循环变量B
行,包括前导空格/制表符。因此,一般来说,定义一个空的定界符列表会更好。
FOR 默认情况下会忽略空行和以分号开头的行,因为;
在默认情况下会被解释为行尾字符。因此,此处使用不常见的,不是双引号的选项字符串delims^=^ eol^=
来定义一个空的定界符列表,并且没有行尾字符。插入符号^
用于转义下一个字符,以使它被解释为原义字符,而不是参数分隔符,尽管它没有包含在双引号引起来的字符串中。
但是此解决方案存在一个问题:包含一个或多个感叹号!
的行未正确处理,因为Windows命令处理器在命令行set "data=%%B"
上将每个!
解释为开始/延迟的环境变量引用的结尾,并用该名称的环境变量的当前值替换两个感叹号之间的字符串,或者使用该名称的不存在的变量将其替换为空,并删除!
之后的所有内容(如果没有)更多!
。
至少有三种解决方案。
第一个是在循环中启用和禁用延迟扩展。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F delims^=^ eol^= %%B in ('%*') do (
set "data=%%B"
setlocal EnableDelayedExpansion
set "data=!data:|=!"
echo(!data!
endlocal
)
endlocal
请阅读this answer,以获取有关命令 SETLOCAL 和 ENDLOCAL 的详细信息,因为它们的作用不只是切换循环中的延迟扩展开/关。 / p>
如果行仅包含(
,而行中仅包含echo
,而行中仅包含空格或制表符,则使用{p} data
和环境变量|
之间的
data
1}}变为未定义或仅由空格/制表符组成的字符串。 echo
和!data!
之间的空格将仅在命令echo
上执行,该命令带有忽略的空格和0个或多个空格/制表符,从而导致获得输出ECHO is off.
而不是空行或仅包含空格/制表符的行。右方括号防止出现这种情况,并由cmd.exe
解释为命令echo
及其参数字符串之间的分隔符,在这种情况下,该字符串始终以(
开始。 ECHO 会忽略输出中参数字符串的第一个字符,只要参数字符串不是/?
且永远不会输出(
。
第二种解决方案是使用子例程:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F delims^=^ eol^= %%B in ('%*') do (
set "data=%%B"
call :ProcessLine
)
endlocal
goto :EOF
:ProcessLine
set "data=%data:|=%"
echo(%data%
goto :EOF
注意:如果行中包含重定向操作符echo %data%
和<
或操作符>
之类的字符,&
可能导致意外行为Windows命令处理器将环境变量echo(%data%
的当前字符串替换为%data%
后执行data
。根据包含set "data=%data:|=%"
和"
的行,甚至<>&
也会有问题。因此,此解决方案确实不安全。
另请参阅Where does GOTO :EOF return to?
第三个解决方案是使用“双百分数”环境变量引用并使用命令 CALL 强制对包含%%variable%%
而不是%variable%
的命令行进行双重解析像往常一样。
@echo off
setlocal EnableExtensions DisableDelayedExpansion
for /F delims^=^ eol^= %%B in ('%*') do (
set "data=%%B"
call set "data=%%data:|=%%"
call echo(%%data%%
)
endlocal
注意另外,根据作为第二种解决方案的数据,该解决方案并不十分安全。
另请参阅How does the Windows Command Interpreter (CMD.EXE) parse scripts?
Windows命令处理器设计用于执行命令和应用程序,而不用于使用竖线作为分隔符/分隔符来重新格式化或处理CSV文件。
要了解所使用的命令及其工作方式,请打开命令提示符窗口,在其中执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面。
call /?
echo /?
endlocal /?
for /?
goto /?
set /?
setlocal /?
由于使用语法set "variable=value"
而不是set variable=value
或set variable="value"
的原因,还请阅读Why is no string output with 'echo %var%' after using 'set var = text' on command line?上的答案。