从批处理文件中的变量中删除双引号会导致CMD环境出现问题


116

有人可以提供有效且安全的方法从批处理变量中删除报价吗?

我编写了一个批处理文件,该文件成功导入了参数%1,%2,%3等的列表,并将其放入命名变量中。其中一些参数包含多个单词,因此用双引号引起来。

> "Susie Jo" (%1)  
> "Smith Barnes" (%2)  
> "123 E. Main St." (%3)  

接下来,将这些%variables放入命名变量中:

> set FirstName=%1  
> set LastName=%2  
> set ShipAddr=%3  

变量的验证是通过回显完成的。

echo。%FirstName%
echo。%LastName%
echo。%ShipAddr%

结果显示为

"Susie Jo"  
"Smith Barnes"  
"123 E. Main St."  

我需要消除所选变量上的引号。例如,FirstName和LastName在其他地方使用,并且不能包含引号。

在一个测试批处理文件中,我成功使用变量中的〜tilde字符消除了引号。

> set FirstName=%~1
> set LastName=%~2 

我以为我有解决方案,但是我很快在执行批处理文件时遇到了异常行为。突然,CMD无法识别长途旅行。从完整路径正常执行批处理文件

> C:\Documents and Settings\Administrator\My Documents\Txt\batchtest\dataout.bat

退货

> 'C:\Documents' is not recognized as an internal or external command....

因此,似乎在即将到来的%1%2 ...%n变量中添加〜tilde字符引起了一些变化。可能某些环境变量已更改?

我还尝试过使用FOR命令通过各种尝试从​​变量内清除引号。这似乎很尴尬,我无法通过创建变量列表来执行任务来学习如何完成此任务:

像这样的东西:

for %%g in (%FirstName% %LastName%) do (
set %%g=%%~g
set %%h=%%~h
set FirstName=%%~g
set LastName=%%h
echo.%FirstName% %LastName%
)

我认为我有两个问题。

1)我在传入的%1%2变量(%〜1等)中插入〜tilde的“简短而甜美”的想法似乎影响了某些设置,并改变了CMD导航长路径名的方式。

2)我仍在寻找一种干净简单的方法来消除所选命名变量中的引号。

对于那些经验丰富的人的任何帮助将不胜感激。我的技能到此为止了。。。需要一些指导!

编辑12/26/2009 13:36 PST整个批处理文件:

Blockquote
:: dataout.bat
::修订2009年12月25日向传入的%variables添加〜tilde 以消除嵌入的“引号。”
::使用命令行参数写入地址列表
::为QBooks写入数据输出列表IIF导入
::写入RUI的商户订单数据
::用于测试的示例命令行字符串
:: listmail [firstname] [lastname] [“ address string”] [“ city string”] [state] [zip] [Order#] [PurchDate] [Regname] [“名字的姓氏”] [交易ID] [付款方式] [总计] [产品ID] [数量] [价格_每个] [PackPrep] [运费] [CommissionPmt] [发票编号]
::示例:dataout Bellewinkle Moose“ 123 Green Forest Way”“ Vancouver” WA 98664 1004968 2009/5/25“ Bellewinkle Moose”“ Olive Oyl” 101738“帐户” 20.67 FK-1P 1 8.95 3.00 1.39 239
@echo off
cls
c:
cd \
cd文档和设置\管理员\我的文档\ txt \批量测试
回显处理%1%2
:VARISET
::将%n命令行参数转换为字符串变量
set($ FirstName)=%〜1
set($ LastName)=% 〜2
set($ BillingAddress1)=%
〜3 set($ BillingCity)=%
〜4 set($ BillingState) =%
〜5套($ BillingPostal)=%〜6套($ OrderNumber)=%
〜7
套($ Purch_Date)=%〜8
套($ RegistrationName)=%〜9

组($的TransactionID)=%〜9
移位
集合($付款方法)=%〜9

集($总)=%〜9
移位集合($产品识别)=%〜9
移位
集合($数量)=%〜9

组($ Price_Each)=%〜9
移位
集合($ Pack_Prep)=%〜9
移位
集合($船运)=%〜9
移位
集合($ ServiceFee)=%〜9
移位
集合($折扣)=%〜9

组($发票)=%〜9
移位
集合($单价)=%〜9
组_ShipCombName =%($姓)%%($名字)%
回波船组合名称是%_ShipCombName%
暂停
::将字符串变量写入日志文件
echo FN%($ FirstName)%LN%($ LastName)%BA%($ BillingAddress1)%%($ BillingCity)%%($ BillingState)%%($ BillingPostal)%%($ OrderNumber)%%($ Purch_Date)%%($ RegistrationName)%%($ TransactionID)%%($ PaymentMethod)%%($ Total)%%($ ProductIdentifier)%%($ Quantity)%%($ Price_Each) %%($ Pack_Prep)%%($ Shipping)%%($ ServiceFee)%%($ Discount)%%($ Invoice)%%($ UnitPrice)%%_ShipCombName%>> d_out_log.txt
::通过分配帐户服务提供商
IF / i%{$ PaymentMethod)%== Amazon应收账款SET _QBAcct = Amazon.com
:: 2009年12月25日添加了第二个Amazon pm't通用性方法
IF / i%{$ PaymentMethod)%== Amazon SET _QBAcct = Amazon.com
IF / i%($ PaymentMethod)%==主设置_QBAcct = Auth / Net
IF / i%($ PaymentMethod)%== MasterCard SET _QBAcct = Auth / Net
IF / i%($ PaymentMethod)%==签证SET _QBAcct = Auth / Net
IF / i%($ PaymentMethod)%== PayPal SET _QBAcct = PayPalPmts
IF / i%($ PaymentMethod)%==在帐户上SET _QBAcct =%($ RegistrationName)%
IF / i%($ PaymentMethod)%==邮件SET _QBAcct =%($ RegistrationName)%
IF / i%( $ PaymentMethod)%== AMER SET _QBAcct = Auth / Net
IF / i%($ PaymentMethod)%== DISC SET _QBAcct = Auth / Net
::根据QBAccount
IF / i 分配代表指示符%($ PaymentMethod)%== Amazon Receivables SET _Rep = Amazon
:: 2009年12月25日添加了第二个Amazon pm't通用性方法
IF / i%($ PaymentMethod)%== Amazon SET _Rep = Amazon
IF / i%($ PaymentMethod)%== MAST SET _Rep = BlueZap
IF / i%($ PaymentMethod)%== MasterCard SET _Rep = BlueZap
IF / i%($ PaymentMethod)%== Visa SET _Rep = BlueZap
IF / i%($ PaymentMethod)%== PayPal SET _Rep = BlueZap
IF / i%($ PaymentMethod)%==在帐户上SET _Rep = RB
IF / i%($ PaymentMethod)%==邮件SET _Rep = RB
IF / i%($ PaymentMethod)%== AMER SET _Rep = BlueZap
IF / i %($ PaymentMethod)%==磁盘设置_Rep = BlueZap
::检查重复的地址数据
findstr / i / s“%_ShipCombName%” addrlist.txt
回显错误级别:%errorlevel%(
如果错误级别1转到):ADDRWRITE
如果错误级别0转到:地址
:地址
回显%_ShipCombName%>> addrlist.txt
回显%($ BillingAddress1)%>> addrlist.txt
echo%($ BillingCity)%%($ BillingState)%%($ BillingPostal)%>> addrlist.txt
回显。>> addrlist.txt
回显地址文件写入
:ADDRFOUND
回显选择的代表是%_Rep%
回显选择的帐户是:%_QBAcct%
暂停
:: RUI OUT
::将商户ID和RUI订单ID写入RUI
::检查是否有重复的RUI数据在writeRUI.txt
cd ..
cd RegKOut中
找到/ i“%($ OrderNumber)%” writeRUI.txt
回显错误级别:%errorlevel%
如果错误级别1转到:RUIWRITE
如果错误级别0转到:IIFWRITE
:RUIWRITE
回显%($ Invoice)% %($ OrderNumber)%>> writeRUI.txt
::结束写入RUI
:: IIF OUT
:IIFWRITE
::检查writeIIF.txt中是否有重复的发票数据
查找/ i“%($ OrderNumber)%” writeIIF.txt
回显错误级别:%errorlevel%
如果错误级别1 goto:HEADWRITE
如果错误级别0 goto:LINEWRITE
:HEADWRITE
::写标头,发货/处理,折扣,代表和佣金数据到QB IIF导入文件
回显%($ OrderNumber)%%($ Purch_Date)%发票%($ TransactionID)%%_QBAcct%应收帐款%($ Total)%%_Rep %>> writeIIF.txt
回显H / P%($ Pack_Prep)%1吗?>> writeIIF.txt
echo SHP%($ Shipping)%1吗?>> writeIIF.txt
echo DISC%($ Discount)%1吗?>> writeIIF.txt
echo Comm%($ ServiceFee)%1吗?>> writeIIF.txt
:LINEWRITE
IF / i%($ ProductIdentifier)%equ PH-1转到WRITE_DEFA ELSE转到WRITE_DISC
echo%($ ProductIdentifier)%
:WRITE_DISC
::写入从自定义变量解析得到的折价:
echo%($ ProductIdentifier) %%($ Price_Each)%%($ Quantity)%吗?>> writeIIF.txt
转到:EOF
:WRITE_DEFA
:写入从产品数据中解析的默认价格
回声%($ ProductIdentifier)%%($ UnitPrice)%%($ Quantity)%吗?>> writeIIF.txt
转到:EOF
:: 3秒延迟
:: TYPE NUL | CHOICE.COM / N / CY / TY,3> NUL
:EOF


您可以使用PowerShell执行此操作吗?我怀疑如果使用PowerShell,您将获得更多控制权。
罗伯特·哈维

1
我检查了您的批处理文件-似乎工作正常(在我修复了“移位集($ ProductIdentifier)=%〜9“行之后-我认为这是在此处复制粘贴的产物)。
atzz

谢谢罗伯特·哈维;我一直在看着PowerShell。我不是非常有编程经验。.不确定学习曲线会是什么样。我确实有一些使用批处理文件的经验,主要原因是我选择了此文件。我打算编译该批处理,以便使其运行得更快。感谢您的回应。
BobB

谢谢atzz:从那以后,我已经对该批处理文件进行了更多测试,并且我相当有信心〜波浪号和放引号与带有长路径名的CMD问题无关。我只是通过在根目录附近设置一个短名称子目录来消除长路径,从而解决了这一问题。
BobB

无需显示完整的批处理文件。请缩短您的问题。
约旦

Answers:


192

您在末尾有一个额外的双引号,即将其加回到字符串的末尾(从字符串中删除两个引号之后)。

输入:

set widget="a very useful item"
set widget
set widget=%widget:"=%
set widget

输出:

widget="a very useful item"
widget=a very useful item

注意:要将“双引号”替换为“单引号”,请执行以下操作:

set widget=%widget:"='%

注意:要将Bob替换为“世界”(不区分大小写),请执行以下操作:

set widget="Hello World!"
set widget=%widget:world=BobB%
set widget

输出:

widget="Hello BobB!"

就您最初提出的问题而言(将以下代码保存到批处理文件.cmd或.bat中并运行):

@ECHO OFF
ECHO %0
SET BathFileAndPath=%~0
ECHO %BathFileAndPath%
ECHO "%BathFileAndPath%"
ECHO %~0
ECHO %0
PAUSE

输出:

"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"
C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd
"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"
C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd
"C:\Users\Test\Documents\Batch Files\Remove Quotes.cmd"
Press any key to continue . . .

%0是脚本名称和路径。
%1是第一个命令行参数,依此类推。


谢谢,这是我为后SET BathFileAndPath=%~0(实际上,用1我的参数数组开始,所以我用SET BathFileAndPath=%~1
Valamas

您能解释一下为什么要%widget:"=%删除引号吗?
CodyBugstein 2014年

4
@Imray- :old=new在变量扩展中是模式匹配和替换。随着"作为old并没有什么作为new,引号被删除,即使他们是在中间,即使他们是不平衡的。
杰西·奇斯霍尔姆

设置小部件=%widget:“ =%当小部件为空白时,它的行为很奇怪,它返回” =“
Rahul Misra,2016年

43

您的结论(1)听起来是错误的。一定还有其他因素在起作用。

批处理文件参数中的引号问题通常可以通过删除引号来解决%~,然后在适当的地方手动将其放回去。

例如:

set cmd=%~1
set params=%~2 %~3

"%cmd%" %params%

注意周围的引号%cmd%。没有它们,带空格的路径将行不通。

如果您可以发布整个批处理代码,则可以做出更具体的答案。


1
我同意; 在我看来,设置var =%〜1应该就可以了。我将按要求发布整个批处理文件。
BobB

MS参考:使用批处理参数。谁知道修饰符这么多?仅供参考,正式MS文档给出的描述%~1Expands %1 and removes any surrounding quotation marks ("").
cod3monk3y

@ cod3monk3y另外,也可能会问cmd自己有关这些修饰符的信息:call /?有关参数修饰符的帮助,set /?有关变量修饰符的帮助(可能不是很直观)。非常方便。
atzz 2014年

12

我通常使用以下命令从变量中删除所有引号:

set var=%var:"=%

然后在需要的地方再次应用它们,例如:

echo "%var%"

一开始我也遇到了麻烦,结果我发现它:.-在弄清楚这一点之后,一切顺利。大提示!
DaveU

9

花了很多时间尝试以一种简单的方式执行此操作。在仔细查看了FOR循环之后,我意识到我可以只用一行代码就能做到这一点:

FOR /F "delims=" %%I IN (%Quoted%) DO SET Unquoted=%%I

例:

@ECHO OFF
SET Quoted="Test string"

FOR /F "delims=" %%I IN (%Quoted%) DO SET Unquoted=%%I

ECHO %Quoted%
ECHO %Unquoted%

输出:

"Test string"
Test string

当“ SET Quoted = Test string”时,此方法无关。接下来的问题是如何区别不“(双引号)存在与否对谁可能担心,谢谢你在先进。
Rhak Kahr

3

这听起来像是一个简单的错误,您在不应该使用%〜的地方使用它。if%〜的使用不会从根本上改变批处理文件的工作方式,它只是在那种情况下从字符串中删除了引号。


3

我从此链接中学到了,如果您使用的是XP或更高版本,则可以单独使用它:

SET params = %~1

我在这里找不到在Windows 7上可以使用的任何其他解决方案。

为了遍历它们,我这样做:

FOR %%A IN (%params%) DO (    
   ECHO %%A    
)

注意:如果传入的参数通常用空格隔开,则只会得到双引号。


0
  1. 设置widget =“一个非常有用的项目”
  2. 设置小部件
  3. widget =“一个非常有用的项目”
  4. 设置小部件=%小部件:“ =%”
  5. 设置小部件
  6. 设置小部件=非常有用的项目”

"4行中的尾随引号"将字符串加引号。应该将其删除。第4行的语法以%


@ user195488-阅读第3行,如下所示widget="a very useful item"并阅读第6行,如其显示:widget=a very useful item"并理解第7行将是,set widget=%widget:"=%而第8行将观察到显示的行widget=a very useful item不再有尾随引号
杰西·奇斯霍尔姆

0

我以为我有解决方案,但是我很快在执行批处理文件时遇到了异常行为。突然,CMD无法识别长途旅行。从完整路径正常执行批处理文件

C:\ Documents and Settings \ Administrator \ My Documents \ Txt \ batchtest \ dataout.bat

退货

'C:\ Documents'不被识别为内部或外部命令。

这是你的全部问题。CMD无法从命令行理解文件名内部的空格,因此认为您正在尝试传递

和设置\管理员\我的文档\ Txt \ batchtest \ dataout.bat

作为参数

“ C:\ Documents”

程序。

您需要引用它来运行一个批处理文件,该文件在路径中带有空格:

> "C:\Documents and Settings\Administrator\My Documents\Txt\batchtest\dataout.bat"

本来可以的。


0
@echo off

Setlocal enabledelayedexpansion

Set 1=%1

Set 1=!1:"=!

Echo !1!

Echo "!1!"

Set 1=

无论原始参数是否带引号,都应演示是否带引号。

并且,如果要测试是否存在用引号引起来的参数,请将此行放在上面的回显之前:

如果'%1'==''转到yoursub

但是,如果检查是否存在带引号或不带引号的文件,则它是:

如果存在“!1!” 转到其他子项

请注意,单引号和双引号的用法不同。


0

所有答案均已完成。但想添加一件事,

设置名字=%〜1

设置姓氏=%〜2

这条线应该已经起作用,您需要进行一些小的更改。

设置“名字=%〜1”

设置“ LastName =%〜2”

在引号中包含完整的作业。它将删除引用而不会出现问题。这是一种首选的分配方式,可以解决引号中不需要的问题。


0

简单的波浪号语法仅适用于删除传递到批处理文件中的命令行参数周围的引号

SET xyz=%~1

上面的批处理文件代码会将xyz设置为在第一个参数剥离开头和结尾的引号(如果存在)时传递的任何值。

但是,这种简单的波浪号语法不适用于未作为参数传递的其他变量

对于所有其他变量,您需要使用扩展的替换语法,该语法要求您指定要删除的前导和滞后字符。实际上,我们指示您删除第一个和最后一个字符,而不要查看其实际含义。

@SET SomeFileName="Some Quoted file name"
@echo %SomeFileName% %SomeFileName:~1,-1%

如果我们想在删除前检查第一个和最后一个字符的实际引用,我们将需要一些额外的代码,如下所示

@SET VAR="Some Very Long Quoted String"
If aa%VAR:~0,1%%VAR:~-1%aa == aa""aa SET UNQUOTEDVAR=%VAR:~1,-1%
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.