热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

批处理-如何正确分配可能包含引号的任意百分号(%1)或百分比星号(%*)参数?

如何解决《批处理-如何正确分配可能包含引号的任意百分号(%1)或百分比星号(%*)参数?》经验,为你挑选了1个好方法。

在处理我之前的问题时,我遇到了一个我最初解决的类似问题.

实际上,我本月花了一些时间尝试创建一个通用的.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

基本上,它是一切,我能想象到读取进入批量("呼叫")百分比参数:形式%1,%~1,%*在不带引号set x=y,引用set "x=y"并明确援引set x="y"变化.延迟扩展只是为了安全地回显该值(!为简单起见,这里我不关心参数中的检查标记).

我的最终目标是创建一个永远不会抛出错误的脚本:因此每个可能的错误都应该出现在我的代码执行之前(在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,使用临时文件 - 什么?)

我很好,即使它会破坏这些情况下的原始字符串(不成对的引号,未转义的特价等),但我需要摆脱解析错误(导致不受控制的代码执行)!



1> jeb..:

你无法用正常的百分比扩展来解决它!
证明:
样本参数是"&"&.
要使用此参数调用批处理文件,您必须转义第二个&符号.

test.bat "&"^&

使用普通命令无法处理此问题,因为您始终会获得一个未加引号的&符号.

set arg=%1
set "arg=%1"
set arg=%~1
set "arg=%~1"

每行都将失败并显示错误消息.

是否有任何命令不会失败%1%*
是的,REM可以正确处理它们.

这没有错误.

REM %1

...

有趣,但如何使用REM声明获取内容有什么好处?
首先,您必须启用ECHO ON才能看到它确实有效.

echo on
REM %1

好了,现在你看到了调试输出

c:\ temp> REM"&"&

现在您只需要将调试输出重定向到文件.
有很多方法都行不通.

@echo on
> arg.txt REM %1
( REM %1 ) > arg.txt
call :func > arg.txt

..
:func 
REM %1

call redirections itself works, but in the func itself you can't access the%1个FOR`环anymore.
But there is one solution to grab the output, with a

(
    @echo on
    for %%a in (42) do (
        rem %1
    ) 
) > arg.txt

是否更好地将参数存储在文件中而不是%1
是的,因为文件可以独立于内容的安全方式读取.

还有一些陷阱离开,像/?,^%%a在争论.
但这一切都可以解决.

@echo off
setlocal DisableDelayedExpansion
set "prompt=X"
setlocal DisableExtensions
(
    @echo on
    for %%a in (4) do (
        rem #%1#
    ) 
) > XY.txt
@echo off
echo x
endlocal
for /F "delims=" %%a in (xy.txt) DO (
  set "param=%%a"
)
setlocal EnableDelayedExpansion
set param=!param:~7,-4!
echo param='!param!'

有关
SO主题的更多信息:如何接收最奇怪的命令行参数?
SO:接收多行参数

对于Drag&Drop,您需要一个更复杂的解决方案SO:拖放多个文件的批处理文件?

编辑:%*
必须禁用扩展的解决方案,否则%a--%~a将修改参数.
但是没有扩展,%*扩展就不再起作用了.
因此,扩展功能只是为了扩展,%*但在FOR显示内容之前,扩展将被禁用.

@echo off
setlocal EnableExtensions DisableDelayedexpansion
set "prompt=-"
(
    setlocal DisableExtensions    
    @echo on
    for %%a in (%%a) do (
        rem # %*#
    )
) > args.tmp
@echo off
endlocal

set "args="
for /F "tokens=1* delims=#" %%G in (args.tmp) DO if not defined args set "args=%%H"
setlocal EnableDelayedExpansion
set "args=!args:~1,-4!"
echo('!args!'

这可以以安全的方式获取所有参数,但是对于来自拖放操作的参数,即使这还不够,因为windows有一个bug(设计缺陷).
像这样的文件Documents&More无法以这种方式获取.


推荐阅读
  • 【Windows】实现微信双开或多开的方法及步骤详解
    本文介绍了在Windows系统下实现微信双开或多开的方法,通过安装微信电脑版、复制微信程序启动路径、修改文本文件为bat文件等步骤,实现同时登录两个或多个微信的效果。相比于使用虚拟机的方法,本方法更简单易行,适用于任何电脑,并且不会消耗过多系统资源。详细步骤和原理解释请参考本文内容。 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • 本文介绍了如何在Azure应用服务实例上获取.NetCore 3.0+的支持。作者分享了自己在将代码升级为使用.NET Core 3.0时遇到的问题,并提供了解决方法。文章还介绍了在部署过程中使用Kudu构建的方法,并指出了可能出现的错误。此外,还介绍了开发者应用服务计划和免费产品应用服务计划在不同地区的运行情况。最后,文章指出了当前的.NET SDK不支持目标为.NET Core 3.0的问题,并提供了解决方案。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了三种方法来实现在Win7系统中显示桌面的快捷方式,包括使用任务栏快速启动栏、运行命令和自己创建快捷方式的方法。具体操作步骤详细说明,并提供了保存图标的路径,方便以后使用。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • CentOS 7部署KVM虚拟化环境之一架构介绍
    本文介绍了CentOS 7部署KVM虚拟化环境的架构,详细解释了虚拟化技术的概念和原理,包括全虚拟化和半虚拟化。同时介绍了虚拟机的概念和虚拟化软件的作用。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • 本文介绍了win7系统休眠功能无法启动和关闭的解决方法,包括在控制面板中启用休眠功能、设置系统休眠的时间、通过命令行定时休眠、手动进入休眠状态等方法。 ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • DSP中cmd文件的命令文件组成及其作用
    本文介绍了DSP中cmd文件的命令文件的组成和作用,包括链接器配置文件的存放链接器配置信息、命令文件的组成、MEMORY和SECTIONS两个伪指令的使用、CMD分配ROM和RAM空间的目的以及MEMORY指定芯片的ROM和RAM大小和划分区间的方法。同时强调了根据不同芯片进行修改的必要性,以适应不同芯片的存储用户程序的需求。 ... [详细]
author-avatar
apiaoapiao_622
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有