在处理先前的问题时,我遇到了一个类似的问题,最初是为了解决它而努力。
实际上,我花了这个月的时间尝试创建一个通用的.bat帮助库,以尽可能处理任何名称的拖放文件。我想透明地为调用者执行此操作,并与任何现有脚本向后兼容,因此文件名作为%1、%2传递,并且我对此没有问题。
@MCND的解决方案是读取%CMDCMDLINE%
然后进行复杂的解析。所以我可以像这样简单地写set "a=%CMDCMDLINE:"=?%"
——就会将完整的字符串写入变量A中,但是其中所有的引号立即被替换为问号?
,导致我可以轻松进一步处理未引用的行。
但它只适用于.bat的拖放,因为这样我无法读取从命令提示符传递的参数。我必须使用%*
。
我的当前问题是:如果参数可能包含引号字符,甚至是不成对的引号,该怎么读取它呢?
考虑以下BAT文件:(我们称之为“C:\test.bat”)
@echo off
echo START
setlocal enabledelayedexpansion
set a=%1
echo a=[!a!]
set b="%1"
echo b=[!b!]
set "c=%1"
echo c=[!c!]
set d=%~1
echo d=[!d!]
set e="%~1"
echo e=[!e!]
set "f=%~1"
echo f=[!f!]
set g=%*
echo g=[!g!]
set h="%*"
echo h=[!h!]
set "i=%*"
echo i=[!i!]
endlocal
echo DONE
exit /b
基本上,它是我能想象到的一切,用于读取传入批处理("call")百分比参数:在未引用的
set x=y
、引用的set "x=y"
和显式引用的set x="y"
变体中,形式为%1
、%~1
、%*
。延迟扩展仅用于安全地回显值(这里我不关心参数中的检查标记!
,以简化问题)。我的最终目标是创建一个永远不会抛出错误的脚本:因此,每一个可能的错误都应该在我的代码执行之前(在CMD提示符本身)或之后(当调用者尝试访问具有损坏名称的文件时)出现。
因此,在此示例中,在START和DONE之间理想情况下不应出现任何错误,但它们将出现在相应的"echo"之前的"set"指令中。 尝试 #1 命令:
test
输出:START
a=[]
b=[""]
c=[]
d=[]
e=[""]
f=[]
g=[]
h=[""]
i=[]
DONE
很好,在零参数下没有错误。让我们加一些参数:
尝试 #2
命令:test 123 "56"
输出:
START
a=[123]
b=["123"]
c=[123]
d=[123]
e=["123"]
f=[123]
g=[123 "56"]
h=["123 "56""]
i=[123 "56"]
DONE
看起来对于“普通”的字符串,任何方法都可以无错误地工作。
尝试 #3
命令:test ^&-
输出:
START
'-' is not recognized as an internal or external command,
operable program or batch file.
a=[]
b=["&-"]
c=[&-]
'-' is not recognized as an internal or external command,
operable program or batch file.
d=[]
e=["&-"]
f=[&-]
'-' is not recognized as an internal or external command,
operable program or batch file.
g=[]
h=["&-"]
i=[&-]
DONE
如您所见,案例A、D和G失败了(=%1
,=%~1
和=%*
)。
尝试 #4
命令:test "&-"
输出:
START
a=["&-"]
'-""' is not recognized as an internal or external command,
operable program or batch file.
b=[""]
'-""' is not recognized as an internal or external command,
operable program or batch file.
c=[]
'-""' is not recognized as an internal or external command,
operable program or batch file.
d=[]
e=["&-"]
f=[&-]
g=["&-"]
'-""' is not recognized as an internal or external command,
operable program or batch file.
h=[""]
'-""' is not recognized as an internal or external command,
operable program or batch file.
i=[]
DONE
现在B、C、D、H和I案例失败了(
="%1"
、"=%1"
、=%~1
、="%*"
和"=%*"
)。
尝试 #5
命令:test ""^&-"
输出:START
'-"' is not recognized as an internal or external command,
operable program or batch file.
a=[""]
b=["""&-""]
c=[""&-"]
d=["&-]
'-"' is not recognized as an internal or external command,
operable program or batch file.
e=[""]
'-"' is not recognized as an internal or external command,
operable program or batch file.
f=[]
'-"' is not recognized as an internal or external command,
operable program or batch file.
g=[""]
h=["""&-""]
i=[""&-"]
DONE
在E和F两个案例中失败了(="%~1"
和"=%~1"
),与A和G(=%1
和%*
)一起。
因此,“set”变量的任何变体都不能可靠地在所有尝试中破坏我的代码!
我是否漏掉了一些其他方法来读取来自不受信任的源的当前参数?
我能否在普通变量%…%
中获得%…
?我能否直接在%…
中替换引号"
?我能否将%*
放在某些特殊上下文中,例如&符号&
可能不会导致执行更改?是否有另一种获取参数的方式(再次调用CMD,使用临时文件-任何内容)?
即使在这些情况下(未配对的引号,未转义的特殊字符等)破坏原始字符串,我也没关系,但我需要摆脱解析错误(导致不受控制的代码执行)!
test ""^&-"
更改为test ""^&-^"
... - aschipfl