FOR / F中的字符串替换为批处理文件

时间:2015-09-25 01:33:40

标签: windows batch-file cmd

有一些关于SO的问题看起来很相似,但我无法弄清楚某些行为,我正在寻求帮助。

下面是我试图编写的批处理文件的片段,它将加载到一组目录中,并可能用扩展路径替换字母替换,例如属性文件可能如下所示:

location1=C:\Test
location2=[m]\Test

location1指向C:\Testlocation2指向C:\Program Files(x86)\MODULE\Test,因为[m]C:\Program Files(x86)\MODULE的简写。

到目前为止,批处理脚本只是尝试读取文件路径列表并展开/替换[m]。

SET build.dir=%~dp0%

SET progfiles=%PROGRAMFILES(X86)%
IF "%progfiles%"=="" SET progfiles=%ProgramFiles%

SET local.properties=%build.dir%local.properties

SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=1* delims==" %%i IN (%local.properties%) DO (

   SET local.dir=%%j
   SET local.dir=!local.dir:[m]=%progfiles%\MODULE!

echo !local.dir!
)
ENDLOCAL

运行此操作会产生错误:

  

\ MODULE此时出乎意料。

如果我用以下内容替换FOR:

set test="[m]\Proj\Dir"
set test=!test:[m]=%progfiles%\MODULE!
echo %test%

我打印出了所需的C:\Program Files(x86)\MODULE\Proj\Dir ...所以我很困惑为什么它在FOR循环之外正常工作。

我对延迟扩张的理解是它扩展了'在运行时...使用!!而不是%%缠绕变量来实现。此外,当我在local.dir循环范围内创建FOR变量时,我必须使用延迟扩展才能使用更新的迭代值来访问它。

我觉得这个问题正在使用%progfiles%,就像我需要使用一些特殊的语法才能让它工作但是没有任何东西可以帮助我。当我echo %progfiles%时,它打印为C:\Program Files(x86 - 请注意缺少的尾随。)

有什么想法吗?感谢

经过测试的建议:

D:\Projects\Test\Build>test
*** "D:\Projects\Test\Build\local.properties"
*** "","C:\Program Files (x86)"
[m]=C:\Program Files (x86)\MODULE

在整个表达式周围添加引号使其工作 - 由于某种原因(如[])无法使用其他字符 - 并且由于我想稍后追加到路径,我们可以安全地删除引号:

SET local.dir="!local.dir:[m]=%progfiles%\MODULE!"
SET local.dir=!local.dir:"=!

2 个答案:

答案 0 :(得分:2)

测试一下,看看你能否解决问题:

双引号用于在具有长文件/路径名的系统中提供可靠的处理。

()是未加引号的,这是批处理脚本中的一个问题,当在循环中时。

@echo off
SET "build.dir=%~dp0%"

SET "progfiles=%PROGRAMFILES(X86)%"
IF "%progfiles%"=="" "SET progfiles=%ProgramFiles%"

SET "local.properties=%build.dir%local.properties"
echo *** "%local.properties%"
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "usebackq tokens=1* delims==" %%i IN ("%local.properties%") DO (

   SET "local.dir=%%j"
echo *** "!local.dir!","%progfiles%"
   SET "local.dir=!local.dir:[m]=%progfiles%\MODULE!"

echo !local.dir!
)
ENDLOCAL
pause

答案 1 :(得分:0)

它与()字符串中最后出现的progfiles个字符有关。如果你把它们拿出来,替换似乎工作正常。

我的建议是为此特定目的抛弃命令,并使用Windows附带的其他标准工具之一。虽然我的个人偏好是Powershell(因为它功能强大且富有表现力),但您可能只需要快速的东西就可以集成到现有的cmd.exe内。

在这种情况下,请尝试以下VBScript文件xlat.vbs

set arg = wscript.arguments
wscript.echo Replace(arg(0),arg(1),arg(2))

您的批处理文件会变成类似的内容,注意 inner for /f,它捕获VBS脚本的输出并将其分配给变量:

@echo off
SET build.dir=%~dp0%

set progfiles=%PROGRAMFILES(X86)%
if "%progfiles%"=="" set progfiles=%ProgramFiles%

set local.properties=%build.dir%local.properties

setlocal enabledelayedexpansion
for /f "tokens=1* delims==" %%i in (%local.properties%) do (
    set local.dir=%%j
    for /f "delims=" %%x in ('cscript.exe //nologo xlat.vbs "!local.dir!" "[m]" "%progfiles%\MODULE"') do set local.dir=%%x
    echo !local.dir!
)
endlocal

运行它,我得到输出:

C:\Test
C:\Program Files (x86)\MODULE\Test

我认为这就是你所追求的目标。