簡體   English   中英

如何將變量的值保留在使用“延遲擴展本地”模式的Windows批處理腳本之外?

[英]How to keep the value of a variable outside a Windows batch script which uses “delayed expansion local” mode?

上下文 :我需要調用一個Windows批處理腳本,它會通過在其末尾添加另一個路徑' xxx '來更新我的PATH ,但是:

  • 沒有任何重復
    (如果我將' xxx '添加到像' aaa;xxx;bbb '這樣的PATH ,我需要更新的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會話中更新?

頁面“ DOS - 函數集合 ”提供了一個很好的例子,說明函數如何在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

請注意使用的路徑串聯。 正如傑布 評論

如果您的路徑包含與C:\\Documents&Settings中的&符號,則行set P=%P%;%~2是至關重要的。
更好地改變設置“ 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答案指向一個更強大的答案(upvoted),但在我的情況下,這個腳本就足夠了。

問題並不像你想象的那么簡單。 有許多問題可能會破壞您的代碼,直到它需要在ENDLOCAL障礙中返回更新的值。

我已經回答了這個問題,作為我為類似問題提供的答案的延伸。 請參見如何檢查%PATH%中是否存在目錄? 在那個答案中,我提供了一系列使問題復雜化的問題。
鏈接答案底部的代碼顯示了如果在PATH中不存在路徑時如何可靠地添加路徑,並且還演示了如何在ENDLOCAL障礙中可靠地返回值。

以下編輯來自VonC,試圖將答案實際放在此處,而不僅僅是答案的鏈接。 我將保留編輯,但我發現很難在沒有完整鏈接答案的上下文的情況下遵循。

[答案演示了如何使用set "%~1=%var%" !可靠地返回值] 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

好極了! 最后使用以下測試代碼:

@echo off
Setlocal enabledelayedexpansion

Set p="hello world"

( endlocal & rem return

   Set "a1=%p%"

)

Set a1

這輸出:

a1="hello world"

我在測試中使用延遲擴展而不使用任何!的原因是因為它仍然會影響設置的工作方式,而我正在為所有人測試的批次都會延遲擴展。

謝謝你的幫助:o)

PS我嘗試在本地和外部環境中使用相同的變量名稱,但這破壞了代碼。 因此使用了2個名字。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM