13

上下文:我需要调用一个 Windows 批处理脚本,该脚本将通过在其末尾PATH添加另一个路径“ ”来更新我,但是:xxx

  • 没有任何重复
    (如果我将 ' xxx' 添加到 PATH 之类的 ' aaa;xxx;bbb',我需要一个更新PATH的 ' aaa;bbb;xxx')
  • 没有任何聚合
    (我可以重复调用脚本而不会以' aaa;bbb;xxx;xxx;xxx;...'结束)

我试过的:

以下功能负责处理任何重复并完成工作

:cleanAddPath -- remove %~1 from PATH, add it at the end of PATH
SETLOCAL ENABLEDELAYEDEXPANSION
set PATH=!PATH:%~2=!
set PATH=!PATH:;;=;!
set PATH=%PATH%;%~2
set P=!P:;;=;!
echo %PATH%
echo -------------
ENDLOCAL  
exit /b

但是,它需要延迟扩展本地模式,这意味着:在脚本的末尾(或这里,在函数的末尾cleanAddPath),设置的任何内容%PATH%都会被丢弃

我可以要求用户(我为此编写脚本)启动他们cmdcmd /V:ON选项(激活延迟扩展,否则默认关闭),但这不切实际。

如何按照我上面描述的方式修改变量,并且在调用所述脚本PATH仍然在我当前的 DOS 会话中更新它?

4

3 回答 3

8

DOS - Function Collection ”页面给出了一个很好的例子,说明一个函数如何在 DOS 中返回一个值,即使在使用延迟扩展模式时也是如此:

以下函数将通过添加更新您想要的任何变量PATH

:cleanAddPath -- remove %~2 from %~1, add it at the end of %~1
SETLOCAL ENABLEDELAYEDEXPANSION
set P=!%~1!
set P=!P:%~2=!
set P=!P:;;=;!
set P=!P!;%~2
set P=!P:;;=;!
(ENDLOCAL & REM.-- RETURN VALUES
  SET "%~1=%P%"
)
exit /b

注意使用的路径连接。正如杰布 评论

如果您的路径包含像 in 之类的 & 符号,则该行set P=%P%;%~2至关重要C:\Documents&Settings
最好更改设置“ P=!P!;%~2”。

SET "%~1=%P%"是允许记住(在由 表示的变量中%~1)您使用延迟扩展功能设置的值的部分。
我最初使用 SET "%~1=%P%" !,但jeb 评论

该命令SET "%~1=%P%" !可以简化SET "%~1=%P%"为尾随感叹号仅在延迟扩展模式下(如果您%P%之前准备好)具有(良好)效果。

要更新您的PATH变量,您可以使用以下命令调用您的函数:

call :cleanAddPath PATH "C:\my\path\to\add"

对于您当前的 DOS 会话,它会在离开该脚本后持续存在。

dbenham答案指向一个更强大的答案(赞成),但在我的情况下,这个脚本就足够了。

于 2012-08-18T16:16:07.673 回答
3

问题并不像你想象的那么简单。有许多问题可能会在您的代码到达终点之前破坏您的代码,因为它需要跨越ENDLOCAL障碍返回更新的值。

我已经回答了这个问题,作为我为类似问题提供的答案的扩展。请参阅如何检查 %PATH% 中是否存在目录?. 在那个答案中,我提供了大量使问题复杂化的问题。
链接答案底部的代码显示了如何可靠地添加路径,如果它已经不存在PATH,它还演示了如何可靠地返回跨越ENDLOCAL障碍的值。

以下编辑来自 VonC,试图将答案实际放在这里,而不仅仅是答案的链接。我会保留编辑,但如果没有完整链接答案的上下文,我很难理解。

[答案演示了如何可靠地返回值]使用set "%~1=%var%" !技巧(尾随' !')

该线程包括:

我不清楚。最后一个引号后面的感叹号如何影响变量内容?

延迟扩展的简单规则是:
对于行中的每个字符,请执行以下操作:

  • 如果是插入符号 ( ^),则下一个字符没有特殊含义,插入符号本身将被删除
  • 如果是感叹号,搜索下一个感叹号(此处不观察脱字符号),然后展开到变量的内容
  • 如果在此阶段没有找到感叹号,则丢弃结果,使用前一阶段的结果(对于插入符号很重要)

因此,此时差异应该很明显,即使感叹号在一行中没有其他效果,插入符号也会被删除。
例子:

@echo off
setlocal EnableDelayedExpansion

echo one caret^^
echo none caret^^  !

set "var1=one caret^"
set "var2=none caret^" !

echo !var1!
echo !var2!
----- OUTPUT ----
one caret^
none caret
one caret^
one caret
于 2012-08-18T16:27:41.317 回答
2

耶!最终使用以下测试代码完成了这项工作:

@echo off
Setlocal enabledelayedexpansion

Set p="hello world"

( endlocal & rem return

   Set "a1=%p%"

)

Set a1

这输出:

a1="hello world"

我在测试中使用延迟扩展而不使用任何!的原因是因为它仍然影响 set 的工作方式,并且我正在为所有人测试的批次延迟扩展。

感谢您的帮助:o)

PS 我尝试对本地和外部环境使用相同的变量名,但这破坏了代码。因此使用了 2 个名称。

于 2016-03-26T17:06:09.140 回答