批处理-带有感叹号(!)和延迟扩展的设置/重置参数调用子例程吗? [英] Batch - Set/Reset parameters calling subroutine with exclamation mark (!) and delayed expansion?

查看:89
本文介绍了批处理-带有感叹号(!)和延迟扩展的设置/重置参数调用子例程吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有2个使用延迟扩展的Locals. 1. Local调用一个子例程,该例程包含2. Local,它定义2个变量,并使用FOR /F ...将这些变量的值设置为参数值.只要字符串不包含一个或多个感叹号,此方法就可以正常工作.以下工作脚本显示了该问题:

I have 2 Locals using delayed expansion. The 1. Local calls a subroutine which includes the 2. Local which defines 2 variables and set the values of those as the parameter values using FOR /F .... This works fine as long as the string do not include one or more exclamation marks. The following working script shows the issue:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION

    CALL :get_substrings testString substr
    ECHO Inside 1. local:
    ECHO !testString!
    ECHO !substr!

    EXIT /B 0
ENDLOCAL


:get_substrings
    SETLOCAL ENABLEDELAYEDEXPANSION

    SET string="World^! wasserschutzpolizei^!"
    SET substring="Hello^!"
    ECHO Inside get_substrings:
    ECHO !string!
    ECHO !substring!

    FOR /F "delims=" %%s IN ("!string!") DO FOR /F "delims=" %%b IN ("!substring!") DO (
        ENDLOCAL & SET "%1=%%s" & SET "%2=%%b" & EXIT /B 0
    )
EXIT /B 0

输出:

Inside get_substrings:
"World! wasserschutzpolizei!"
"Hello!"
Inside 1. local:
"World"
"Hello"

预期:

Inside get_substrings:
"World! wasserschutzpolizei!"
"Hello!"
Inside 1. local:
"World! wasserschutzpolizei!"
"Hello!"

如果删除stringsubstring中的感叹号,脚本将按预期工作.

If you remove the exclamation marks in string and substring the script works as expected.

因为这只是一个示例,请考虑...

Because this is just an Example consider...

  1. 不使用延迟扩展也不是一种选择,而且...
  2. 不希望使用一个Local.

当然,如果确实需要一件事或什至两件事,而且我没有其他办法接受其他指出这一点的答案.

Of course, if one or even both things are REALLY required and there is no other way I accept other answers pointing that out.

所以...

  1. 如何像我在 Expected 部分中显示的那样,在1. local中获取带有感叹号的值?
  2. 为什么它不能与当前设置参数值的方式一起使用?
  1. How can get the values with exclamation mark in the 1. local like i showed in the Expected part?
  2. Why doesn't it work with the current way of setting the param values?

感谢您的帮助!

推荐答案

将您的:get_substrings函数的返回部分更改为:

Change the return part of your :get_substrings function to:

...
set "return1=!string:"=""!"
set "return1=%return1:!=^^^!%"
set "return1=!return1:""="!"

set "return2=!substring:"=""!"
set "return2=%return2:!=^^^!%"
set "return2=!return2:""="!"

FOR /F "delims=" %%s IN ("!return1!") DO FOR /F "delims=" %%b IN ("!return2!") DO (
    ENDLOCAL & SET "%1=%%s" & SET "%2=%%b" & EXIT /B 0
)

但是为什么您的解决方案失败?
问题是set "%1=%%s"是在延迟扩展上下文中执行的,因为您的整个批处理都使用延迟扩展.
但是延迟扩展是批处理解析器的最后一个扩展阶段,它是在%%s的参数扩展之后. 因此,解析器尝试扩展感叹号,当这里只有一个感叹号时,它将被删除,当在"World! wasserschutzpolizei!"中有两个类似的感叹号时,它会将变量! wasserschutzpolizei!扩展为其值(在您的情况下,它似乎为空).

But why your solution fails?
The problem is that the set "%1=%%s" is executed in a delayed expansion context, as your complete batch uses delayed expansion.
But delayed expansion is the last expansion phase of the batch parser and it's after the parameter expansion of the %%s.
Therefore the parser tries to expand your exclamation marks, when here is only one it will be removed, when there are two like in "World! wasserschutzpolizei!" it expand the variable ! wasserschutzpolizei! to it's value (in your case it seems to be empty).

该解决方案只是将尖号放在任何感叹号的前面.
但是,您还在示例中使用了引号,这会使更多事情变得更加复杂.
为了避免引号和插入符号出现问题,这是一种将所有引号加倍的简单方法,添加插入号并将更改后的双引号更改回单引号.

The solution simply put carets in front of any exclamation mark.
But you are also using quotes in your samples it makes more things more complicated.
To avoid problems with quotes and carets it's an easy way to double all quotes, add the carets and the change the doubled quotes back to single quotes.

这篇关于批处理-带有感叹号(!)和延迟扩展的设置/重置参数调用子例程吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆