从批处理文件中的变量中删除双引号会给 CMD 环境带来问题

有没有人能够帮助我们从批处理变量中移除引号?

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

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

这些% 变量接下来放在命名变量中:

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

变量的验证是通过回声来完成的。 > echo.% FirstName%
> echo.% LastName%
> 回声

结果显示为

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

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

在一个测试批处理文件中,我成功地在变量中使用 ~ 波浪形字符消除了引号。

> 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 变量中添加 ~ 波浪字符似乎已经引起了一些变化。可能一些环境变量被改变了?

我还尝试使用 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等)中插入 ~ 波浪线的“简短而甜蜜”的想法似乎影响了一些设置,并改变了 CMD 导航长路径名的方式。

  2. 我仍然在寻找一种简单明了的方法来消除选定的命名变量中的引号。

对于那些更有经验的人的任何帮助将是最感激的。我在这里已经没有办法了... 需要一些指导!

2009年12月26日太平洋标准时间13:36 整个批处理文件:

:: dataout.bat
:: revision 12/25/2009 add ~tilde to incoming %variables to eliminate embedded "quotation marks.
:: writes address list using command line parameters
:: writes data output list for QBooks IIF import
:: writes Merchant Order data for RUI
:: sample command line string for testing
:: listmail[firstname][lastname]["address string"]["city string"][state][zip][Order#][PurchDate][Regname]["FirstName LastName"][TransactionID][PaymentMethod][Total][ProductID][Qty][Price_Each][PackPrep] [Shipping] [CommissionPmt] [Invoice#]
:: example: dataout Bellewinkle Moose "123 Green Forest Way" "Vancouver" WA 98664 1004968 05/25/2009 "Bellewinkle Moose" "Olive Oyl" 101738 "On Account" 20.67 FK-1P 1 8.95 3.00 1.39 239
@echo off
cls
c:
cd\
cd documents and settings\administrator\my documents\txt\batchtest
echo processing %1 %2
:VARISET
:: Convert %n command line parameters to string variables
set ($FirstName)=%~1
set ($LastName)=%~2
set ($BillingAddress1)=%~3
set ($BillingCity)=%~4
set ($BillingState)=%~5
set ($BillingPostal)=%~6
set ($OrderNumber)=%~7
set ($Purch_Date)=%~8
set ($RegistrationName)=%~9
shift
set ($TransactionID)=%~9
shift
set ($PaymentMethod)=%~9
shift
set ($Total)=%~9
shift
set ($ProductIdentifier)=%~9
shift
set ($Quantity)=%~9
shift
set ($Price_Each)=%~9
shift
set ($Pack_Prep)=%~9
shift
set ($Shipping)=%~9
shift
set ($ServiceFee)=%~9
shift
set ($Discount)=%~9
shift
set ($Invoice)=%~9
shift
set ($UnitPrice)=%~9
set _ShipCombName=%($FirstName)% %($LastName)%
echo ship combo name is %_ShipCombName%
pause
:: write string varibables to logfile
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
:: Assign Account by Service Provider
IF /i %($PaymentMethod)%==Amazon Receivables SET _QBAcct=Amazon.com
:: 12-25-2009 added second Amazon pm't method for versatility
IF /i %($PaymentMethod)%==Amazon SET _QBAcct=Amazon.com
IF /i %($PaymentMethod)%==MAST SET _QBAcct=Auth/Net
IF /i %($PaymentMethod)%==MasterCard SET _QBAcct=Auth/Net
IF /i %($PaymentMethod)%==Visa SET _QBAcct=Auth/Net
IF /i %($PaymentMethod)%==PayPal SET _QBAcct=PayPalPmts
IF /i %($PaymentMethod)%==On Account SET _QBAcct=%($RegistrationName)%
IF /i %($PaymentMethod)%==Mail SET _QBAcct=%($RegistrationName)%
IF /i %($PaymentMethod)%==AMER SET _QBAcct=Auth/Net
IF /i %($PaymentMethod)%==DISC SET _QBAcct=Auth/Net
:: Assign Rep designator based on QBAccount
IF /i %($PaymentMethod)%==Amazon Receivables SET _Rep=Amazon
:: 12-25-2009 added second Amazon pm't method for versatility
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)%==On Account SET _Rep=R B
IF /i %($PaymentMethod)%==Mail SET _Rep=R B
IF /i %($PaymentMethod)%==AMER SET _Rep=BlueZap
IF /i %($PaymentMethod)%==DISC SET _Rep=BlueZap
:: check for duplicate address data
findstr /i /s "%_ShipCombName%" addrlist.txt
echo errorlevel: %errorlevel%
if errorlevel 1 goto :ADDRWRITE
if errorlevel 0 goto :ADDRFOUND
:ADDRWRITE
echo %_ShipCombName% >> addrlist.txt
echo %($BillingAddress1)% >> addrlist.txt
echo %($BillingCity)% %($BillingState)% %($BillingPostal)% >> addrlist.txt
echo. >> addrlist.txt
echo Address File Written
:ADDRFOUND
echo selected rep is %_Rep%
echo selected account is: %_QBAcct%
pause
:: RUI OUT
:: write Merchant Order ID & RUI Order ID to RUI
:: check for duplicate RUI data in writeRUI.txt
cd..
cd RegKOut
find /i "%($OrderNumber)%" writeRUI.txt
echo errorlevel: %errorlevel%
if errorlevel 1 goto :RUIWRITE
if errorlevel 0 goto :IIFWRITE
:RUIWRITE
echo %($Invoice)%   %($OrderNumber)% >> writeRUI.txt
:: end write RUI
:: IIF OUT
:IIFWRITE
:: Check for duplicate invoice data in writeIIF.txt
find /i "%($OrderNumber)%" writeIIF.txt
echo errorlevel: %errorlevel%
if errorlevel 1 goto :HEADWRITE
if errorlevel 0 goto :LINEWRITE
:HEADWRITE
:: write Header, Ship/Handling, discount, Rep & commission data to QB IIF import file
echo %($OrderNumber)%   %($Purch_Date)% Invoice %($TransactionID)%  %_QBAcct%   Accounts Receivable             %($Total)%  %_Rep% >> writeIIF.txt
echo                        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 goto WRITE_DEFA ELSE goto WRITE_DISC
echo %($ProductIdentifier)%
:WRITE_DISC
::writes discounted prices parsed from custom variable:
echo                        %($ProductIdentifier)%  %($Price_Each)% %($Quantity)%   ? >> writeIIF.txt
goto :EOF
:WRITE_DEFA
:writes default prices parsed from Product data
echo                        %($ProductIdentifier)%  %($UnitPrice)%  %($Quantity)%   ? >> writeIIF.txt
goto :EOF
:: 3-second delay
:: TYPE NUL | CHOICE.COM /N /CY /TY,3 >NUL
:EOF


198832 次浏览

你的结论(1)听起来不对,一定有其他因素在起作用。

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

例如:

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


"%cmd%" %params%

注意 %cmd%附近的引号。没有它们,带空格的路径就不能工作。

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

这听起来像是一个简单的 bug,您在不该使用% ~ 的地方使用了% ~ 。If% ~ 的使用并没有从根本上改变批处理文件的工作方式,它只是在这种情况下从字符串中删除了引号。

我通常只是从我的变量中移除所有引号:

set var=%var:"=%

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

echo "%var%"

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

输入:

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:"='%

注意: 要用 BobB 代替“ World”(不区分大小写) ,请执行以下操作:

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是第一个命令行参数,以此类推。

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

第4行中的引号 "正在向字符串中添加一个引号 ",应该删除它。 第4行的语法以 %结束

花了很多时间试图用一种简单的方式来做这件事。 在仔细查看 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

我从这个 链接中学到,如果你正在使用 XP 或者更高版本,那么它会自己工作:

SET params = %~1

我无法得到任何其他解决方案在这里工作的 Windows 7。

为了重复这些步骤,我这样做:

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

注意: 如果传入的参数通常由空格分隔,那么只会得到双引号。

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

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

报税表

“ C: 文档”不被认为是内部或外部命令... ..。

这就是你的问题所在。CMD 不理解来自命令行的文件名中的空格,因此它认为您正在尝试传递

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

作为参数

C: 文件

程序。

您需要引用它来运行路径中包含空格的批处理文件:

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

会有用的。

@echo off


Setlocal enabledelayedexpansion


Set 1=%1


Set 1=!1:"=!


Echo !1!


Echo "!1!"


Set 1=

无论原始参数是否带引号,都可以使用引号或不带引号进行演示。

如果你想测试一个参数的存在性,这个参数可能是引号,也可能不是引号,把这一行放在上面的回声之前:

如果“% 1”= = “进入你的子系统

但是,如果检查是否存在一个可能有引号或可能没有引号的文件,那么它是:

如果存在“ ! 1!”去其他子

注意单引号和双引号的使用是不同的。

所有的答案都是完整的,但是我想补充一点,

Set FirstName =% ~ 1

Set LastName =% ~ 2

这句台词应该有用的,你需要一个小小的改变。

设置“ FirstName =% ~ 1”

设置“ LastName =% ~ 2”

在引号中包含完整的作业。它会毫无问题地删除引号。这是一种首选的赋值方式,用参数中的引号修复不想要的问题。

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

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%

Azure devops 有时使用双引号字符(")来指定字符串。Powershell 可以使用单引号字符(')来指定字符串。自然,我希望有一个灵活性,能够指定参数,但我希望,所以相同的参数可以使用两个命令行-通过批处理文件,并作为一个 powershell 脚本,作为任何参数,包括空值。

引用自然思维是这样写的:

build.bat:


@echo off
setlocal enabledelayedexpansion
set args=%*
set args=%args:"='%
echo powershell -executionpolicy bypass "%~dpn0.ps1" %args%
endlocal

但是正如您可以猜测的那样,如果没有为批处理文件提供参数,那么 %* = = 空字符串,那么这种方法就不能立即执行。args展开为没有字符串,并且下一个替换注意到没有设置 args-而且不替换字符串-它将向 args参数附加额外的 "='垃圾。

解决这个问题的方法只是在第一次作业中增加额外的空间。

build.bat:


@echo off
setlocal enabledelayedexpansion
set args=%*
set args=%args:"='%
echo powershell -executionpolicy bypass "%~dpn0.ps1" %args%
endlocal

这个字符之后的翻译应该是正确的:

C:\test>build
powershell -executionpolicy bypass "C:\test.ps1"


C:\test>build aa
powershell -executionpolicy bypass "C:\test\build.ps1" aa


C:\test>build "aa"
powershell -executionpolicy bypass "C:\test\build.ps1" 'aa'


C:\test>build 'aa'
powershell -executionpolicy bypass "C:\test\build.ps1" 'aa'