我正在尝试删除变量中的字符!
。
setlocal enableextensions enabledelayedexpansion
set filename=!filename:!=_!
我已经尝试用^
来逃避它,但这不起作用。
Set filename=!filename:^!=_!
如何摆脱变量中的!-sign?
答案 0 :(得分:4)
使用正常扩展时,无法替换%
。您必须使用延迟扩展:!var:%%=_!
同样,在使用延迟扩展时,您无法替换!
。您必须使用正常扩展:%var:!=_%
。
但如果您的变量可能包含^
,&
,|
,>
,<
等毒性字符的混合,则可能会出现问题以及报价。例如,在以下字符串中没有单一步骤替换!
:"This & that" & the other thing!
诀窍是分阶段进行更换,主要使用延迟扩展,使用正常扩展替换一次。
1)延迟展开 - 将"
转换为""
2)正常扩展 - 将!
转换为replacement
。因为所有报价都加倍,所以现在保证扩展的外部报价可以保护所有毒药
3)延迟展开 - 将""
转换回"
@echo off
setlocal enableDelayedExpansion
set "var="This ^& that" & the other thing^!"
echo before: !var!
set "var=!var:"=""!"
set "var=%var:!=_%"
set "var=!var:""="!"
echo after: !var!
- 输出 -
before: "This & that" & the other thing!
after: "This & that" & the other thing_
但是你正在处理文件名,这可以使问题更简单: - )
文件名可以包含毒药字符&
和^
,但它们不能包含引号。您可以在文件名(或路径)中的任何位置放置引号,它们将保护有毒字符。但是当操作系统在磁盘上存储或查找文件时,操作系统会删除引号。
所以我通常会确保我的文件名和路径变量不包含引号。然后简单地使用是安全的:
set "filename=%filename:!=_%"
哎呀 - 我刚刚读了问题评论,看到这是在一个循环中!
在循环中发生替换这一事实使事情复杂化,因为正常扩展不会看到循环中定义的值。
请注意,展开FOR变量时必须关闭延迟扩展,否则会损坏文件名中的!
。
最简单的解决方案是使用CALL进行额外的扩展:
@echo off
setlocal disableDelayedExpansion
for %%F in (*) do (
set "file=%%F"
call set "file=%%file:!=_%%"
setlocal enableDelayedExpansion
echo file=!file!
endlocal
)
如果您正在进行其他需要延迟扩展的操作,那么!
将需要在正常的扩展替换表达式中进行转义,因为在CALL之前会发生延迟扩展。 (谢谢jeb)。
以下是一个消除^
和&
的示例。
@echo off
setlocal disableDelayedExpansion
for %%F in (*) do (
set "file=%%F"
setlocal enableDelayedExpansion
set "file=!file:^=_!"
set "file=!file:&= and !"
call set "file=%%file:^!=_%%"
echo file=!file!
endlocal
)
虽然我可以在之后启用延迟展开,但我已经删除了!
。然后就不需要逃脱了。
答案 1 :(得分:2)
目前唯一突然出现的是子程序和隧道:
@echo off
set "line=!---!asd!asd!"
setlocal enableDelayedExpansion
echo !line!
call :subr "!line!" line
echo !line!
endlocal
exit /b %errorlevel%
:subr
setlocal disableDelayedExpansion
set "string=%~1"
set "res=%string:!=$%"
endlocal && (
set "%~2=%res%"
)
只需在脚本末尾定义这样的子程序,并在for循环中调用它