如何将参数传递给包含%而没有“破坏”的批处理文件?

时间:2016-09-27 08:43:14

标签: batch-file

问题

在主批处理文件中,值从.txt文件中提取(和SET作为此批处理文件中的变量值)。这些值可能每个都包含%个字符。

这些是从.txt文件中读取的,没有任何问题。但是,当具有包含%字符的值的变量传递给第二个批处理文件时,第二个批处理文件将任何%个字符解释为变量扩展。 (注意:对第二个批处理文件有控制权。)

示例

echo %PERCENTVARIABLE%

输出:I%LOVE%PERCENT%CHARACTERS%

当传递给第二个文件然后回显时,(可能)会变成IPERCENT,因为它将%LOVE%%CHARACTERS%解释为未设置的变量

研究

我找到了在批处理文件中查找和替换字符串中元素的语法,因为我认为我可以用%替换%%字符以逃避它。但是我无法让它发挥作用。

语法为 -

set string=This is my string to work with.
set string=%string:work=play%
echo %string%

输出将为This is my string to play with.

问题

  1. 是否可以使用查找和替换语法转义% 字符  在一个变量? (如果没有,还有其他办法吗?)
  2. 建议这样做吗?(可能使用这些转义字符导致第二个批处理文件中的任何问题(如上所述)我们无法控制吗?)
  3. 如果无法解决此问题,还有其他方法吗?

2 个答案:

答案 0 :(得分:2)

没有简单的规则可以在所有情况下应用。

有一些问题使得在参数中使用字符串文字很困难:

  1. 必须转义或引用&|等毒药字符。逃避是困难的,因为它可能会混淆多少次逃脱。所以建议通常引用字符串。
  2. 除非引用,否则<space><tab>=;,等令牌分隔符不能包含在参数值中。
  3. 对脚本的CALL会将所有引用的%字符加倍,并且 无法阻止此 。执行不带CALL的脚本不会使%个字符加倍。但是,如果脚本调用另一个脚本并期望返回控制,则必须使用CALL。
  4. 所以我们有一个catch-22:一方面,我们想引用参数来防止毒性字符和空格(令牌分隔符)。但为了保护百分比,我们不想引用。

    可靠地传递字符串文字而不关心值损坏的唯一可靠方法是通过环境变量通过引用传递它们。

    1. 要传递的值应存储在环境值中。引号和/或转义和/或百分比加倍用于获取值中的必要字符,但它非常易于管理。
    2. 变量的名称作为参数传入。
    3. 脚本通过延迟扩展访问该值。例如,如果第一个参数是包含该值的变量的名称,则将其作为!%1!访问。必须先启用延迟扩展才能使用该语法 - 只需发出setlocal enableDelayedExpansion
    4. 延迟扩展的美妙之处在于,当扩展变量时,您永远不必担心毒性字符,空格或百分比的损坏。

      这是一个示例,显示如何将以下字符串文字传递给子例程
      "<%|,;^> This & that!" & the other thing! <%|,;^>

      @echo off
      setlocal enableDelayedExpansion
      set "parm1="^<%%^|,;^^^^^> This ^& that^^!" & the other thing^! <%%|,;^^^>"
      echo The value before CALL is !parm1!
      call :test parm1
      exit /b
      
      :test
      echo The value after  CALL is !%1!
      

      - 输出 -

      The value before CALL is "<%|,;^> This & that!" & the other thing! <%|,;^>
      The value after  CALL is "<%|,;^> This & that!" & the other thing! <%|,;^>
      

      但是你声明你无法控制第二个被调用的脚本。所以上面优雅的解决方案对你不起作用。

      如果您要显示第二个脚本的代码,并准确显示您尝试传递的值,那么我可能能够提供一个可以在这种孤立情况下工作的解决方案。但是除非使用变量名称进行延迟扩展,否则有些值根本无法传递。 (实际上,另一种选择是将值放在文件中并从文件中读取值,但这也需要更改到第二个脚本)

答案 1 :(得分:1)

可能是......?

input.txt

I%LOVE%PERCENT%CHARACTERS%

batch1.bat

@echo off
setlocal enableDelayedExpansion
set/P var=<input.txt
echo(In batch 1 var content: %var%

set "var=!var:%%=%%%%!"
call batch2.bat "%var%"
endlocal
exit/B

batch2.bat

@echo off
set "var=%~1"
echo(In batch 2 var content: %var%
exit/B