奇怪的行为与批处理功能参数的特殊字符? [英] Strange behavior with special characters in arguments of batch functions?

查看:233
本文介绍了奇怪的行为与批处理功能参数的特殊字符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设你运行 test.bat的布拉布拉,布拉布拉,^>布拉布拉,布莱比

实施下的test.bat:

test.bat implementation:

@SETLOCAL
@ECHO OFF
SET list=%~1
ECHO "LIST: %list%"
ECHO "ARG 1: %~1"
ECHO "ARG 2: %~2"
@ENDLOCAL   
@GOTO :EOF

如预期输出:

"LIST: blabla,blabla,>blabla"
"ARG 1: blabla,blabla,^>blabla"
"ARG 2: blaby"

但如果你让test.bat的批处理文件中的函数:

But what if you make test.bat a function inside a batch file:

@SETLOCAL
CALL :TEST "blabla,blabla,^>blabla", "blaby"
@ENDLOCAL
@GOTO :EOF

:TEST
@SETLOCAL
@ECHO OFF
SET list=%~1
ECHO "LIST: %list%"
ECHO "ARG 1: %~1"
ECHO "ARG 2: %~2"
@ENDLOCAL   
@GOTO :EOF

它运行后的输出是:

After running it the output is:

"LIST: blabla,blabla,^"
"ARG 1: blabla,blabla,^^>blabla"
"ARG 2: blaby"

咦?


  1. 哪儿了布拉布拉走在LIST?

  2. ARG 1具有 ^ ^ ?为什么呢?

  1. Where did blabla go in the LIST?
  2. ARG 1 has ^^? Why?

有人能解释如何特殊字符函数参数不同的行为,而不是命令行参数?

Can someone explain how special characters behave differently in function arguments as opposed to command line arguments?

推荐答案

您可以简单地通过使用得到您的第一个批处理脚本同样的结果:

You can get the same result with your 1st batch script simply by using:

call test.bat "blabla,blabla,^>blabla", "blaby"

您的问题从批处理如何解析CALL语句一个不幸的方面干。这是在第6阶段的描述如何在Windows命令国米preTER(CMD.EXE)解析脚本?

Your problems stem from an unfortunate aspect of how batch processing parses CALL statements. It is described in phase 6 at How does the Windows Command Interpreter (CMD.EXE) parse scripts?.

哎哟 - 我想我明白了插入符之前增加了一倍,但显然不是。我大量编辑响应杰布的评论下面的讨论。

CMD.EXE的设计者希望像一份声明中称回声^^ 来产生相同的结果为回声^^ 。这两个语句减少 ^ ^ ^ 在特殊字符的处理阶段2。但是,CALL语句要经过第一阶段和第二阶段第二次。所以在幕后,当CMD.EXE识别阶段6 CALL语句,双打,其余插入符回 ^ ^ ,然后第二轮第二阶段减少回到 ^ 。这两个语句呼应单尖到屏幕上。

The designers of CMD.EXE want a statement like call echo ^^ to give the same result as echo ^^. Both statements reduce ^^ to ^ in phase 2 where special characters are handled. But the CALL statement has to go through phase 1 and phase 2 a second time. So behind the scenes, when CMD.EXE recognizes the CALL statement in phase 6, it doubles the remaining caret back to ^^ and then the second round of phase 2 reduces it back to ^. Both statements echo a single caret to the screen.

不幸的是盲目的CMD.EXE所有双打插入符,即使它们被引用。但引用插入符不被视为一种逃避,它是文字。插入记号不再消耗。非常不幸的。

Unfortunately CMD.EXE blindly doubles all carets, even if they are quoted. But a quoted caret is not treated as an escape, it is a literal. The carets are no longer consumed. Very unfortunate.

运行的test.bat叫布拉布拉,布拉布拉,^>布拉布拉,布莱比变成的test.bat叫布拉布拉,布拉布拉^^方式>布拉布拉,布莱比在分析器阶段6

Running call test.bat "blabla,blabla,^>blabla", "blaby" becomes call test.bat "blabla,blabla,^^>blabla" "blaby" in phase 6 of the parser.

这很容易解释为什么ARG 1看起来像它在输出一样。

That easily explains why ARG 1 looks like it does in your output.

至于放哪儿布拉布拉去?这只是一个有点棘手。

As far as where did blabla go?, that is just a bit trickier.

在你的脚本执行 SET列表=%〜1 ,引号都去掉了,在 ^ ^ 被处理作为逃脱插入符降低到 ^ > 不再逃跑。所以,你的SET语句的输出重定向到一个布拉布拉文件。当然,SET没有输出,所以你应该把你的硬盘驱动器上的零长度布拉布拉文件。

When your script executes SET list=%~1, the quotes are removed, the ^^ is treated as an escaped caret which reduces to ^, and the > is no longer escaped. So the output of your SET statement is redirected to a "blabla" file. Of course SET has no output so you should have a zero length "blabla" file on your hard drive.

编辑 - 如何使用迟到扩张正确地传递所需的参数

在他的回答,试图达沃尔扭转插入符调用例程内翻番的效果。但是,这是不可靠的,因为你无法知道到底有多少次插入记号可能已经增加了一倍。如果你让主叫调整通话,而不是为了补偿这是更好。这是有难度的 - 你必须使用什么杰布称为迟到扩张

In his answer, davor attempted to reverse the effect of the caret doubling within the called routine. But that is not reliable because you cannot know for sure how many times the carets may have been doubled. It is better if you let the caller adjust the call to compensate instead. It is tricky - you have to use what jeb called "late expansion"

在一个批处理脚本,您可以定义包含所需参数字符串变量,然后推迟扩建以后才脱字符被另一个%逃避%翻了一番。您需要双倍的百分比在声明中每个呼叫。

Within a batch script you can define a variable that contains the desired argument string, and then delay the expansion until after carets are doubled by escaping the % with another %. You need to double the percents for each CALL in the statement.

@echo off
setlocal
set arg1="blabla,blabla,^>blabla"
call :TEST %%arg1%% "blaby"
echo(
call call :TEST %%%%arg1%%%% "blaby"
::unquoted test
exit /b

:TEST
setlocal
set list=%~1
echo "LIST: %list%"
echo "ARG 1: %~1"
echo "ARG 2: %~2"
exit /b

上面的产生所期望的结果:

The above produces the desired result:

"LIST: blabla,blabla,>blabla"
"ARG 1: blabla,blabla,^>blabla"
"ARG 2: blaby"

"LIST: blabla,blabla,>blabla"
"ARG 1: blabla,blabla,^>blabla"
"ARG 2: blaby"

在命令行中运行时的扩展规则是不同的。这是不可能的命令行逃脱%。相反,当插入符号在第二阶段被剥离,你必须添加一个插入符的百分数内的$ P $从一号通识别名称pvents扩张阶段,然后扩展的第2次正确扩展变量。

The expansion rules are different when run from the command line. It is impossible to escape a % from the command line. Instead you must add a caret within the percents that prevents the expansion phase from recognizing the name on the 1st pass, and then when the caret is stripped in phase 2, the 2nd pass of expansion properly expands the variable.

以下用途达沃尔的原始TEST.BAT

The following uses davor's original TEST.BAT

C:\test>test.bat "blabla,blabla,^>blabla" "blaby"
"LIST: blabla,blabla,>blabla"
"ARG 1: blabla,blabla,^>blabla"
"ARG 2: blaby"

C:\test>set arg1="blabla,blabla,^>blabla"

C:\test>test.bat %arg1% "blaby"
"LIST: blabla,blabla,>blabla"
"ARG 1: blabla,blabla,^>blabla"
"ARG 2: blaby"

C:\test>call test.bat %^arg1% "blaby"
"LIST: blabla,blabla,>blabla"
"ARG 1: blabla,blabla,^>blabla"
"ARG 2: blaby"

C:\test>set arg2=%^arg1%

C:\test>call call test.bat %^arg2% "blaby"
"LIST: blabla,blabla,>blabla"
"ARG 1: blabla,blabla,^>blabla"
"ARG 2: blaby"

以逃避的另一种 - 通过引用传递值

所有的一切,逃避规则是可笑的复杂。这就是为什么先进的批量脚本经常被引用,而不是作为文字传递的字符串值。所需的字符串放在一个变量,然后将变量的名称被作为参数传递。延迟扩展来得到确切的字符串,而不必担心损坏,由于特殊字符或CALL插入符号加倍或百分比剥离。

All in all, the escape rules are ridiculously complicated. That is why advanced batch scripting often passes string values by reference instead of as literals. The desired string is placed in a variable and then the name of the variable is passed as an argument. Delayed expansion is used to get the exact string without fear of corruption due to special characters or CALL caret doubling or percent stripping.

下面是一个演示概念的简单test.bat的

Here is a simple test.bat that demonstrates the concept

@echo off
setlocal enableDelayedExpansion
set "var1=!%~1!"
echo var1=!var1!

call :test var1
exit /b

:test
set "var2=!%~1!"
echo var2=!var2!

这里是它如何工作的示范。

And here is a demonstration of how it works.

C:\test>set complicatedString="This & that ^" ^& the other thing ^^ is 100% difficult to escape

C:\test>set complicatedString
complicatedString="This & that ^" & the other thing ^ is 100% difficult to escape

C:\test>test.bat complicatedString
var1="This & that ^" & the other thing ^ is 100% difficult to escape
var2="This & that ^" & the other thing ^ is 100% difficult to escape

C:\test>call test.bat complicatedString
var1="This & that ^" & the other thing ^ is 100% difficult to escape
var2="This & that ^" & the other thing ^ is 100% difficult to escape

C:\test>call call test.bat complicatedString
var1="This & that ^" & the other thing ^ is 100% difficult to escape
var2="This & that ^" & the other thing ^ is 100% difficult to escape

这篇关于奇怪的行为与批处理功能参数的特殊字符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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