如何将变量的值保留在使用“0”的Windows批处理脚本之外;“本地延迟扩展”;模式

如何将变量的值保留在使用“0”的Windows批处理脚本之外;“本地延迟扩展”;模式,windows,path,batch-file,environment-variables,Windows,Path,Batch File,Environment Variables,上下文:我需要调用一个Windows批处理脚本,该脚本将通过在其末尾添加另一个路径“xxx”来更新我的路径,但是: 没有任何副本 (如果我将“xxx”添加到类似于“aaa;xxx;bbb”的路径中,我需要更新的路径,类似于“aaa;bbb;xxx”) 没有任何聚合 (我可以重复调用脚本,而不会以“aaa;bbb;xxx;xxx;xxx;…”结尾) 我所尝试的: 下面的函数负责处理任何副本并执行此任务 :cleanAddPath -- remove %~1 from PATH, add it

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

  • 没有任何副本
    (如果我将“
    xxx
    ”添加到类似于“
    aaa;xxx;bbb
    ”的路径中,我需要更新的
    路径,类似于“
    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%
设置的任何内容都会被丢弃

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

如何以上述方式修改
路径
变量,并在调用所述脚本后在当前DOS会话中对其进行更新?

页面“”给出了函数如何在DOS中返回值的极好示例,即使在使用模式时也是如此:

以下函数将使用添加的
路径
更新所需的任何变量:

: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
请注意使用的路径连接。作为:


设置p=%p%;%~如果您的路径包含类似于
C:\Documents&Settings

最好改为设置“
P=!P!;%~2

设置“%~1=%p%”
是允许记忆(在由
%~1
表示的变量中)使用延迟扩展功能设置的值的部分。
我最初使用
设置“%~1=%P%”,但:

命令
设置“%~1=%p%”可以简化为
设置“%~1=%P%”
,因为后面的感叹号在延迟扩展模式下只有(良好)效果,而且如果您以前准备了
%P%

要更新
路径
变量,可以使用以下命令调用函数:

call :cleanAddPath PATH "C:\my\path\to\add"
在离开该脚本后,它将持续存在,用于当前的DOS会话


这是一个更为有力的答案(投票表决),但就我而言,这个脚本就足够了。

问题并不像你想象的那么简单。有许多问题可能会在代码结束之前中断代码,代码需要跨
ENDLOCAL
屏障返回更新后的值

我已经回答了这个问题,作为我为类似问题提供的答案的延伸。看见在这个答案中,我列出了一大串使问题复杂化的问题。
链接答案底部的代码显示了如果路径在
path
中不存在,如何可靠地添加路径,并且还演示了如何可靠地跨
ENDLOCAL
屏障返回值

以下编辑来自VonC,旨在将答案放在此处,而不仅仅是答案的链接。我将保留编辑,但如果没有完整链接答案的上下文,我很难理解。

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

该线程包括:

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

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

  • 如果是插入符号(
    ^
    ),则下一个字符没有特殊含义,插入符号本身将被删除
  • 如果是感叹号,则搜索下一个感叹号(此处不观察插入符号),然后展开到变量的内容
  • 如果在此阶段中未找到感叹号,则放弃结果,而是使用之前阶段的结果(对于插入符号很重要)
因此,在这一点上,区别应该很明显,即使感叹号在一行中没有其他效果,插入符号也会被删除。
例如:


耶!最终通过以下测试代码实现了这一点:

@echo off
Setlocal enabledelayedexpansion

Set p="hello world"

( endlocal & rem return

   Set "a1=%p%"

)

Set a1
这将产生:

a1="hello world"
我在测试中使用延迟扩展而不使用任何这是因为它仍然影响集合的工作方式,而我正在测试的所有批处理都延迟了扩展

谢谢你们的帮助,伙计们:o)


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

很有趣+1.我重新使用了
集合“%~1=%P%”在我的答案中的一部分,以便在“延迟扩展”函数之外正确返回我的更新值。请不要调用Windows命令解释器DOS。“这真的不是同一件事。”哈利约翰斯顿我同意。abatishchev的编辑似乎很好地解决了这个问题。谢谢你的abatishchev。@问题是只在CMD本地会话中更改环境变量,而不是用户或系统环境变量。因此,我的脚本足以允许我的用户在本地更改其路径(而不影响默认情况下由其环境变量设置的相同路径)
set P=%P%;%~如果路径中包含类似于
C:\Documents&Settings
中的符号,则2
是关键。最好改为
设置“P=!P!;%~2”
。命令
设置“%~1=%P%”
可以简化为
设置“%~1=%P%”
,因为尾部感叹号在延迟扩展模式下只有(良好)效果,并且如果您准备了
%P%
before@jeb好的观点。我编辑了我的答案以反映您的评论。使用
1
(一)作为变量名是一个非常糟糕的主意,因为您无法使用百分比访问它
a1="hello world"