禁用在括号变量扩展的块中准备一个字符串,以将其返回到可以扩展的呼叫范围(不允许呼叫)
我只有在Windows批处理脚本中才要求理论知识目的。
今天,我的问题是要准备本地字符串loc_str
在一个括号的块内而无需延迟扩展,以将其返回到启用变量外汇的本地范围(或最终准备它)对于in(“%loc_str%”)
,如果loc_str中的讨厌字符已正确逃脱)。
我们假设loc_str
至少包含一个^
和一个!
,并且不包含双引号。让我们考虑以下代码:
@echo off
setlocal disabledelayedexpansion
set "flag_dde_prev=%flag_dde%" & set "flag_dde=!"
(
set "loc_str=Hello^^^ planet!!!! ^^Earth^"
if not defined flag_dde_prev (
call set "out_str=%%loc_str:^=^^%%"
set out_str
call set "out_str=%%out_str:^=^^%%"
set out_str
)
)
endlocal & set "str=%out_str%"
set str
如您所知,本地标志flag_ {dde,dde_prev}
用于测试调用和当前范围的类型。通常,它们都在块setLocal..endLocal
的开头定义。 flag_dde
等于!
如果当前范围禁用变量扩展,或者不确定 如果当前范围可以启用它。 flag_dde_prev
的本地值是调用范围中flag_dde
的继承值。
我们必须在这里做的是逃脱所有^
和!
,准备OUT_STR
的返回,并使用%..%..%
当后者启用变量扩展时(即定义flag_dde_prev
时)时,要进行调用范围。两个替代^= ^^
然后用简单的设置
就足够了,但是在一个块(..)力我们使用呼叫集
语句。不幸的是,Caret ^
并未以启用变量扩展的范围中的方式替换。
确切地说,第一个替换^= ^^
偶数均匀的镜头序列,但不会加倍奇数(它使它们翻了一番)。 然后,第二个替换!=^!
用^^!
替换每个!
。
要陷入困境,
loc_str=Hello^^^ planet!!!! ^^Earth^ ;init
out_str=Hello^^^^^ planet!!!! ^^^^Earth^ ;1st substitution ^=^^
out_str=Hello^^^^^ planet^^!^^!^^!^^! ^^^^Earth^ :2nd substitution !=^!
如果仅在^^ =^
仅在!=^!
之前完成,似乎可以使用^^ =^
可逆。 如果^^ =^
是在!=^!
之后完成的,则仅修改^
notefeard !
仅修改。 如果^^ =^
是在!=^!
之后完成的代码>“ 。 在!
之前,它的行为就像序列^^
是原子不可再生的,可以更换更长的caret序列,但我无法获得^!
无论我尝试什么。
当启用可变扩展时,也很容易解决同样的问题,即使通过替换
>” “ ”首先(Jeb已经在另一个方面谈论过这一点),即 )。
set "out_str=!loc_str:^=^^^^!" ;1st substitution, multiplicates the number of ^ by 4 as expected
call set "out_str=%%out_str:^!=^^^!%%" ! ;2nd substitution, replaces each ! by ^^!
set "out_str=!out_str:^^=^!" ;3rd substitution required, replaces each ^^ by ^ to divide by 2 the total number of ^
线程 是否有一种方法在完全相同的上下文中使用替换(即否呼叫
)来获取所需的准备的out_str
>启用延迟扩展?
准备好的输出值应将^
的数量增加一倍,并在每个^
添加^
之前! ie:
out_str=Hello^^^^^^ planet^!^!^!^! ^^^^Earth^^
请注意,这是我的问题仅用于理论知识目的。确实,请称标签以简单的SET
进行两个替换是进行的合理方法。
i have a request for theorical knowledge purpose only in Windows Batch scripting.
Today my question is about preparing the value of a local string loc_str
INSIDE A BLOCK OF PARENTHESIS and WITHOUT ENABLING DELAYED EXPANSION, in order to return it to a local scope that enables variable expasion (or eventually to prepare it for an incoming local for loop with in("%loc_str%")
if nasty characters in loc_str have been properly escaped before).
We assume that loc_str
contains at least one ^
and one !
and do not contain double quotes. Lets consider the following code:
@echo off
setlocal disabledelayedexpansion
set "flag_dde_prev=%flag_dde%" & set "flag_dde=!"
(
set "loc_str=Hello^^^ planet!!!! ^^Earth^"
if not defined flag_dde_prev (
call set "out_str=%%loc_str:^=^^%%"
set out_str
call set "out_str=%%out_str:^=^^%%"
set out_str
)
)
endlocal & set "str=%out_str%"
set str
As you know the local flags flag_{dde, dde_prev}
are used to test the type of the calling and current scopes. Typically they're both defined at the beginning of a block setlocal..endlocal
. The flag_dde
is equal to !
if the current scope disables variable expansion, or is undefined
if the current scope enables it. The local value of flag_dde_prev
is the inherited value of flag_dde
in the calling scope.
What we must do here is to escape all ^
and !
to prepare the return of out_str
with %..%
to the calling scope when this latter enable variable expansion (ie when flag_dde_prev
is defined). Two substitutions ^=^^
then !=^!
with a simple set
would be enough, but being inside a block (..) forces us to use the call set
statement. Unfortunatly the caret ^
is not replaced in the same way they are in a scope that enables variable expansion.
Precisely, the first substitution ^=^^
doubles even sequences of carets, but does not double odd ones (it doubles them minus one).
Then, the second substitution !=^!
replace each !
with ^^!
.
To sump up,
loc_str=Hello^^^ planet!!!! ^^Earth^ ;init
out_str=Hello^^^^^ planet!!!! ^^^^Earth^ ;1st substitution ^=^^
out_str=Hello^^^^^ planet^^!^^!^^!^^! ^^^^Earth^ :2nd substitution !=^!
^=^^
seems to be reversible with ^^=^
if done BEFORE !=^!
only.
If ^^=^
is done after !=^!
then sequences of ^
not preceeding !
are modified only.
If ^^=^
is done after !=^!
i didn't find a way to replace the sequences of ^^
before each "
.
It behaves like a sequence ^^
before !
is the atomic unreplacable one, longer caret sequences can be replaced but i couldn't obtain ^!
whatever i tried.
The same problem is quite easy to solve when variable expansion is enabled, even with nasty strings containing quotes by replacing ""
by "
at first (jeb already talked about this in another thread). For example if locs_tr
doesn't contain quotes, the substitutions would be the following:
set "out_str=!loc_str:^=^^^^!" ;1st substitution, multiplicates the number of ^ by 4 as expected
call set "out_str=%%out_str:^!=^^^!%%" ! ;2nd substitution, replaces each ! by ^^!
set "out_str=!out_str:^^=^!" ;3rd substitution required, replaces each ^^ by ^ to divide by 2 the total number of ^
So my question is simple:
Is there a way using substitution IN THE EXACT SAME CONTEXT (ie no call
) to obtain the desired prepared output value for out_str
, so it can be returned safely to a scope that enables delayed expansion ?
The prepared output value should double the number of ^
and add ^
before each !
ie:
out_str=Hello^^^^^^ planet^!^!^!^! ^^^^Earth^^
Note that's my question is for theorical knowledge purpose ONLY. Indeed calling a label to do the two substitutions with a simple set
is the reasonable way to proceed.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的假设是错误的!
问题在这里,如果行中有感叹号,伦名折叠是不同的!
呼叫
,镜头和感叹号真的很有趣。因为
呼叫
始终在任何其他规则之前将所有镜头加倍,但是您不会用引号看到它,因为在下一个解析器阶段,双重的手套再次折叠为单个镜头。单一线的解析流
几年前,Dbenham和我解决了 。
请参阅 so:离开setLocal范围时要保留变量的宏
或者
so:使环境变量生存在endlocal 中。
在您的情况下,这要简单得多,因为您不支持引号,也不支持变量中的线条。
而且您知道,您会离开当前范围,并将恢复启用延迟扩展的范围,这也简化了问题。
Your assumptions are wrong!
The problem is here the fact that caret folding is different if there is an exclamation mark in the line or not!
call
and carets and exclamation marks are really funny.Because
call
always double all carets before any other rule, but you don't see it with quotes, because in the next parser phase the doubled carets are folded to single carets again.Parse flow for a single line like
The problem itself was solved by dbenham and me a few years ago.
See SO: Macro to preserve variables when leaving setlocal scope
or
SO: Make an environment variable survive ENDLOCAL.
In your case it's much simpler, because you don't support quotes nor line feeds in the variable.
And you know, that you leave the current scope and will return into a scope with delayed expansion enabled, this simplifies the problem, too.
好吧,杰布,我刚刚执行了你的宏。以下代码可以复制并运行。如果我正确理解,那么一般原则就是以下(如果没有,请纠正我)。
感谢您的发言,实际上我说的太快了,LOC_STR的输入值中的“ Q and” e都没有问题。避免使用
rem
的特殊角色,您完全忘记了。我也通过分配flag_dde_prev来键入错误,必须使用!当然是在EDE范围内。我在这里与代码编辑器挣扎,现在我还不习惯这样的东西(是的,我听起来像个洞穴人大声笑)。我编辑了我以前的帖子,返回DDE范围时会跳过保护块(..)(我也忘记了在定义为!时
flag_dde_prev
时分配out_str。返回的受保护字符串到DDE包含令人讨厌的字符,因此不能用%..%
回声,因此我为使用了来呼应它。
有没有一种方法可以处理
“
和& |<>
来保护这样令人讨厌的loc_str,以在带有Brutal的调用dde范围中呼应它。 echo%..%
或呼叫设置%..%
,或者在相反的情况下,无法避免通过slow
echo <避免 回声/code>仅具有
的,或者是非常快的
set str_pro
仅通过删除领先字符串“ str_pro =”
by 值中添加一个动态的backspace在OUT_STR
运行两次,首先在调用范围为DDE时,第二次是EDE(上面的代码中的EDE)。
Ok jeb i just executed your macro. The code below can be copied and run. If i understood properly, the general principle is the following (correct me if i didn't).
Thanks for your remarks, indeed i talked too fast there is no problem at all with ""q and ""e in the input value of loc_str. You're very right about avoiding special characters with
rem
, i totally forgot. I did typing mistake also by assigning flag_dde_prev, it must be done with !..! inside an EDE scope of course. I struggle with the code editor here, i'm not used to such stuffs for now (yes i know i sound like a cavern man lol).I edited my previous post, the protection block (..) is skipped when returning to a DDE scope (i forgot also to assign out_str when
flag_dde_prev
when defined to !). The returned protected string to DDE contains nasty characters so can't be echoed with%..%
, so i used afor
to echo it.Is there a way to deal with
"
and&|<>
to protect a such nasty loc_str to echo it in the calling DDE scope with a brutalecho %..%
orcall set %..%
, or at the contrary is an undirect echoing can't be avoided ?By undirect i mean without a slow
echo
only ie with afor
like above, or with a very fastset str_pro
only by deleting the leading string"str_pro="
by adding a dynamic leading string of backspace in the out_str value.OUTPUT
Run twice, first when the calling scope is DDE, second when it's EDE (written as EDE in the code above).