Windows命令行字符串替换删除“!”

时间:2013-10-16 14:43:07

标签: windows command-line

我有一个小代码片段用production:false取代production:true

(FOR /F "tokens=1,* delims=]" %%A in ('"type test.js|find /n /v """') do (

    set "line=%%B"

    if defined line (
        call set "line=echo.%%line:production:false=production:true%%"
        FOR /F "delims=" %%X in ('"echo."%%line%%""') do %%~X
    ) ELSE echo.

)) >test-temp.js

move /Y test-temp.js test.js

到目前为止一直很好,但是,在test.js中它说的是:

if ( !production ) {}

事情是,“!”也被上述命令删除。知道怎么回事?

3 个答案:

答案 0 :(得分:2)

您可能已调用delayedexpansion

针对您提供的单行数据运行您的代码段(这是您给我们的全部内容),只需逐字复制数据行。

delayedexpansion!在您描述时消失了。


要修复(delayedexpansion生效

SETLOCAL DISABLEDELAYEDEXPANSION
(FOR /F "tokens=1,* delims=]" %%A in ('"type q19406461.txt|find /n /v """') do (
    set "line=%%B"

    if defined line (
             call set "line=echo.%%line:production:false=production:true%%"
             FOR /F "delims=" %%X in ('"echo."%%line%%""') do %%~X
    ) ELSE echo.

)) >test-temp.js
ENDLOCAL

答案 1 :(得分:2)

这是一个强大的方法,并使用名为repl.bat的帮助程序批处理文件 - http://www.dostips.com/forum/viewtopic.php?f=3&t=3855

repl.bat放在与批处理文件相同的文件夹中。

@echo off
type "test.js"|repl "production:false" "production:true" >"test-temp.js"

答案 2 :(得分:2)

彼得已经诊断出延迟扩张的问题了。这是一个更多的解释。

FOR变量在延迟扩展之前扩展。因此,行set "line=%%B"首先将值设置为if ( !production ) {},但是延迟扩展会看到未配对的!并将其删除。如果它是配对的,它会尝试在两者之间扩展变量。

以下是变量扩展顺序的总结(实用,但有点不精确):

1)正常扩展:参数(%1)和变量(%var%)。参数优先于变量。

2)FOR变量:%% A

3)延迟扩展:!var!

4)SET / A变量

有关如何解析和扩展行的详细说明,请参阅How does the Windows Command Interpreter (CMD.EXE) parse scripts

如果您打开和关闭延迟扩展,可以在循环中使用延迟扩展而不会破坏!文字。这比使用CALL语法更受欢迎,因为它更快,不会与%文字混淆,不会引用引用的插入符号,防止所有有毒字符,即使它们没有被引用。

延迟扩展的使用使代码更简单,更快速,更可靠:

setlocal disableDelayedExpansion
(FOR /F "tokens=1,* delims=]" %%A in ('"type test.js|find /n /v """') do (
  set "line=%%B"
  setlocal enableDelayedExpansion
  if defined line (
    echo(!line:production:false=production:true!
  ) ELSE echo(
  endlocal
)) >test-temp.js
move /Y test-temp.js test.js
endlocal

请注意,我使用的是ECHO(而不是ECHO.,因为后者可能会在某些模糊的情况下失败。 ECHO(看起来会导致块括号出现问题,但实际上它总是没有任何问题。

请注意,我仍然不会使用上面的代码。相反,我会在他的回答中使用REPO2.BAT实用程序作为foxidrive。