Удаление двойных кавычек из переменных в пакетном файле создает проблемы со средой 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%
›echo.% ShipAddr%

результаты отображаются как

"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. Я все еще ищу чистый и простой способ удалить кавычки из выбранных именованных переменных.

Любая помощь для более опытных будет очень признательна. Я здесь на исходе ... нужны советы, пожалуйста!

отредактировать 26/12/2009 13:36 PST весь командный файл:

:: 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  


person BobB    schedule 26.12.2009    source источник
comment
Не могли бы вы использовать для этого PowerShell? Я подозреваю, что вы получите немного больше контроля, если будете использовать PowerShell.   -  person Robert Harvey    schedule 26.12.2009
comment
Я проверил ваш командный файл - похоже, он работает нормально (после того, как я исправил набор сдвига строки ($ ProductIdentifier) ​​=% ~ 9 - который, я думаю, является артефактом его копирования и вставки здесь).   -  person atzz    schedule 27.12.2009
comment
Спасибо, Роберт Харви; Я смотрел PowerShell. Я не очень опытен в программировании .. не уверен, что будет походить на кривую обучения. У меня есть некоторый опыт работы с пакетными файлами, основная причина, по которой я выбрал это. Я собираюсь скомпилировать пакет, чтобы он работал быстрее. Спасибо за ответ.   -  person BobB    schedule 29.12.2009
comment
Спасибо atzz: с тех пор я протестировал этот командный файл еще немного, и я достаточно уверен, что ~ тильда и изгоняющие кавычки не связаны с проблемой CMD с длинными путями. Я работал над этим, просто создавая подкаталог коротких имен рядом с корнем, чтобы исключить длинные имена путей.   -  person BobB    schedule 29.12.2009
comment
Нет необходимости показывать полный пакетный файл. Пожалуйста, сократите свой вопрос.   -  person jor    schedule 22.01.2019


Ответы (11)


У вас есть дополнительная двойная кавычка в конце, которая добавляет ее обратно в конец строки (после удаления обеих кавычек из строки).

Вход:

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

Примечание. Чтобы заменить слово «World» (без учета регистра) на BobB, выполните следующие действия:

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 - это первый аргумент командной строки и так далее.

person Mr. Rick    schedule 03.03.2011
comment
Спасибо, это было то, чем я был после SET BathFileAndPath=%~0 (на самом деле, мой массив параметров начинается с 1, поэтому я использовал SET BathFileAndPath=%~1 - person Valamas; 21.01.2014
comment
Вы можете объяснить, почему %widget:"=% избавляется от кавычек? - person CodyBugstein; 21.09.2014
comment
@Imray - :old=new - это совпадение с шаблоном и замена в раскрытии переменной. С " в качестве old и ничем как new, кавычки удаляются, даже если они находятся посередине, даже если они несбалансированы. - person Jesse Chisholm; 12.02.2015
comment
set widget =% widget: =% имеет странное поведение, когда виджет пустой, он возвращает = - person Rahul Misra; 09.12.2016
comment
Боюсь, что это решение не работает, если в строке есть &, как в set widget="hello&world". В этом случае вам нужно использовать set "widget=%widget:"=%" - person Jthorpe; 19.02.2021

Ваш вывод (1) звучит неверно. Должен быть какой-то другой фактор.

Проблема кавычек в параметрах командного файла обычно решается удалением кавычек с %~ и последующим их возвращением вручную, где это необходимо.

E.g.:

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

"%cmd%" %params%

Обратите внимание на кавычки вокруг %cmd%. Без них путь с пробелами работать не будет.

Если бы вы могли опубликовать весь свой пакетный код, возможно, можно было бы дать более конкретный ответ.

person atzz    schedule 26.12.2009
comment
Я согласен; мне кажется, что set var =% ~ 1 должен работать нормально. Я отправлю весь пакетный файл по запросу. - person BobB; 26.12.2009
comment
Ссылка MS: Использование параметры пакета. Кто знал, что существует столько модификаторов? Для справки, официальный документ MS дает описание %~1 как Expands %1 and removes any surrounding quotation marks (""). - person cod3monk3y; 21.01.2014
comment
@ cod3monk3y Кроме того, можно cmd спросить самого себя об этих модификаторах: call /? для помощи по модификаторам параметров, set /? для модификаторов переменных (вероятно, не очень интуитивно). Очень удобно. - person atzz; 23.01.2014

Обычно я просто удаляю все кавычки из своих переменных с помощью:

set var=%var:"=%

А затем примените их снова там, где они мне нужны, например:

echo "%var%"
person t1ck    schedule 02.12.2010
comment
У меня тоже сначала были проблемы с этим, оказалось, что я видел : как . - после того, как разобрался, работал без сучка и задоринки. Отличный совет! - person DaveU; 28.11.2014

Потратил много времени, пытаясь сделать это простым способом. Внимательно посмотрев на цикл 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
person Vitaliy Ulantikov    schedule 10.01.2013
comment
Этот метод не актуален, пока SET Quoted = Test string. Следующий вопрос - как различать существует (двойные кавычки) или нет. Кому это может быть интересно, заранее благодарю вас. - person Rhak Kahr; 18.06.2014

Это похоже на простую ошибку, когда вы используете% ~ где-то там, где вам не следует находиться. Использование if% ~ принципиально не меняет способ работы командных файлов, оно просто удаляет кавычки из строки в этой единственной ситуации.

person John Knoeller    schedule 26.12.2009

Я узнал из этой ссылки, если вы используете XP или выше, что это будет просто работать сам:

SET params = %~1

Я не мог заставить какие-либо другие решения работать в Windows 7.

Чтобы перебрать их, я сделал следующее:

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

Примечание. Вы получите двойные кавычки, только если вы передадите аргументы, разделенные пробелом.

person Community    schedule 01.04.2013

Простой синтаксис тильды работает только для удаления кавычек вокруг параметров командной строки, передаваемых в пакетные файлы.

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%
person user13490680    schedule 03.06.2020

  1. set widget = "очень полезный предмет"
  2. установить виджет
  3. widget = "очень полезный предмет"
  4. установить виджет =% виджет: "=%"
  5. установить виджет
  6. set widget = очень полезный предмет "

Завершающая кавычка " в строке 4 добавляет кавычку " к строке. Его следует удалить. Синтаксис строки 4 заканчивается на %

person David    schedule 18.11.2012
comment
@ user195488 - прочтите строку 3 как обратите внимание, что она отображается: widget="a very useful item" и прочтите строку 6, поскольку обратите внимание, что она отображается: widget=a very useful item" и поймите, что строка 7 будет set widget=%widget:"=%, а строка 8 будет обратите внимание, что отображаемая строка widget=a very useful item больше не имеет завершающей кавычки. - person Jesse Chisholm; 12.02.2015

Я думал, что у меня есть решение, но вскоре я испытал необычное поведение при выполнении командных файлов. Внезапно CMD перестает распознавать состояния длинного пути. Нормальное выполнение командного файла с полного пути

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

возвращается

'C: \ Documents' не распознается как внутренняя или внешняя команда ....

В этом вся твоя проблема. CMD не понимает пробелов внутри имен файлов из командной строки, поэтому думает, что вы пытаетесь передать

и Настройки \ Администратор \ Мои документы \ Txt \ batchtest \ dataout.bat

в качестве параметров

C: \ Документы

программа.

Вам нужно процитировать его, чтобы запустить командный файл с пробелами в пути:

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

сработало бы.

person CarryWise    schedule 12.12.2014

@echo off

Setlocal enabledelayedexpansion

Set 1=%1

Set 1=!1:"=!

Echo !1!

Echo "!1!"

Set 1=

Демонстрирует с кавычками или без них, независимо от того, есть ли кавычки в исходном параметре или нет.

И если вы хотите проверить наличие параметра, который может быть или не быть в кавычках, поместите эту строку перед эхом выше:

Если '% 1' == '' перейти к вашей подписке

Но если проверять наличие файла, который может содержать или не содержать кавычки, то это:

Если СУЩЕСТВУЕТ "! 1!" перейти к другому

Обратите внимание, что использование одинарных и двойных кавычек различается.

person Aaron Lowe    schedule 24.03.2016

Все ответы полные. Но хотел добавить одну вещь,

установить FirstName =% ~ 1

установить LastName =% ~ 2

Эта строка должна была сработать, вам потребовалось небольшое изменение.

установить FirstName =% ~ 1

установить LastName =% ~ 2

Включите полное задание в кавычки. Он удалит кавычки без проблем. Это предпочтительный способ назначения, который устраняет нежелательные проблемы с помощью кавычек в аргументах.

person Code Name Jack    schedule 18.09.2017