批处理 - 转义大于号不起作用

Batch - Escaping greater-than sign doesn't work

在下面的脚本中,我将一个 qouted 字符串传递给一个子例程并取消引用它(访问参数时使用波浪号)以不引用它输出它。不幸的是,我尝试转义大于符号的尝试不起作用:

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
    set foo="Argument -> Not provided^!"
    call :output_actual_error !foo!

    ENDLOCAL
EXIT /B 0

:output_actual_error
    SETLOCAL DISABLEDELAYEDEXPANSION
    set bar=%~1
    set bar=%bar:>=^>%
    echo %bar%
    ENDLOCAL
EXIT /B 0

输出:

Argument - provided!

预计:

Argument -> Not provided!

请注意,代码仅供说明,并不代表实际实现。

那么,如何转义大于号和echo不带双精度的字符串呢?

使用

set "bar=%~1"
set "bar=%bar:>=^>%"

已经提供了解决方案。但是,我想向您展示我将如何编写代码以使其尽可能安全地对抗各种特殊字符的所有组合,方法是使用正确的引号并仅在真正需要的地方启用和应用延迟扩展并在需要的地方禁用它它令人不安或不安全:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem /* No delayed expansion during immediate variable assignment,
rem    so escaping of exclamation marks is not required;
rem    quotation in a way not to become part of the value: */
set "foo=Argument -> Not provided!"
setlocal EnableDelayedExpansion
rem /* Delayed expansion during reading of variable;
rem    quote argument value here to protect white-spaces: */
call :output_actual_error "!foo!"
endlocal
endlocal
exit /B 0


:output_actual_error
    rem /* No delayed expansion during argument expansion (%);
    rem    quotation in a way not to become part of the value: */
    setlocal DisableDelayedExpansion
    set "bar=%~1"
    setlocal EnableDelayedExpansion
    rem // Delayed expansion during reading of variable:
    echo(!bar!
    endlocal
    endlocal
    exit /B 0

这基本上避免了变量赋值和 % 扩展期间的延迟扩展,并在读取变量时使用延迟扩展。

仍然存在失败的风险:

  1. 一个由 call 引入,因为它加倍了引号 (^)。
  2. 另一个由参数扩展 (%~1) 表示,这可能会导致引号出现问题,尤其是当它们看起来不平衡时。