批量替换!-sign

时间:2015-06-14 10:53:58

标签: windows batch-file

我正在尝试删除变量中的字符!

setlocal enableextensions enabledelayedexpansion 
set filename=!filename:!=_! 

我已经尝试用^来逃避它,但这不起作用。

Set filename=!filename:^!=_!

如何摆脱变量中的!-sign?

2 个答案:

答案 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循环中调用它