Удаление двойных кавычек из переменных в пакетном файле создает проблемы со средой CMD

117

Может ли кто-нибудь помочь с эффективным и безопасным способом удаления кавычек из пакетных переменных?

Я написал командный файл, который успешно импортирует список параметров% 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 весь командный файл:

Blockquote
:: dataout.bat
:: редакция 12/25/2009 добавить ~ Тильда входящих% переменных ликвидировать встроенные « в кавычки.
:: записывает список адресов с использованием параметров командной строки
:: записи списка вывода данных для QBooks IIF импорта
:: записи Данные торгового заказа для RUI
:: образец строки командной строки для тестирования
:: listmail [имя] [фамилия] ["адресная строка"] ["городская строка"] [штат] [почтовый индекс] [Заказ №] [PurchDate] [Regname] ["FirstName LastName"] [TransactionID] [PaymentMethod] [Total] [ProductID] [Qty] [Price_Each] [PackPrep] [Shipping] [CommissionPmt] [Invoice #]
:: пример: dataout Bellewinkle Moose "123 Green Forest Way" "Vancouver" WA 98664 1004968 25.05.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 документы и настройки \ администратор \ мои документы \ txt \ batchtest
обработка эха% 1% 2
: VARISET
::Преобразование параметров командной строки% n в
набор строковых переменных ($ FirstName) =% ~ 1
набор ($ LastName) =% ~ 2
набор ($ BillingAddress1) =% ~ 3
набор ($ BillingCity) =% ~ 4
набор ($ BillingState) =% ~ 5
набор ($ BillingPostal) =% ~ 6
набор ($ OrderNumber) =% ~ 7
набор ($ Purch_Date) =% ~ 8
набор ($ RegistrationName) =% ~ 9
смен
($ TransactionID) =% ~ 9
смен
($ PaymentMethod) =% ~ 9
смен
($ Total) =% ~ 9
смен ($ ProductIdentifier) ​​=% ~ 9
смен
($ Quantity) =% ~ 9
смен
($ Price_Each) =% ~ 9
смен
($ Pack_Prep) =% ~ 9
смен
($ Доставка) =% ~ 9
смен
($ ServiceFee) =% ~ 9
смен
($ Discount) =% ~ 9
смен
($ Invoice) =% ~ 9

набор смен ($ UnitPrice) =% ~ 9
набор _ShipCombName =% ($ FirstName)%% ($ LastName)%
имя комбо эхо-корабля% _ShipCombName%
pause
:: записать строковые переменные в файл журнала
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 Поставщик услуг
IF / i% ($ PaymentMethod)% == Amazon Receivables SET _QBAcct = Amazon.com
:: 25.12.2009 добавлен второй метод Amazon pm't для универсальности
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)% == В учетной записи 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
:: Назначить указатель Rep на основе QBAccount
IF / i% ($ PaymentMethod)% == Amazon Receivables SET _Rep = Amazon
:: 25.12.2009 добавлен второй метод 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)% == Mail SET _Rep = RB
IF / i% ($ PaymentMethod)% == AMER SET _Rep = BlueZap
IF / i % ($ PaymentMethod)% == DISC SET _Rep = BlueZap
:: проверить дублирующиеся данные адреса
findstr / i / s "% _ShipCombName%" addrlist.txt
echo errorlevel:% errorlevel%,
если 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
:: записать идентификатор заказа продавца и идентификатор заказа RUI в RUI
:: проверить наличие дубликатов данных RUI в 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
:: Проверить дублирующиеся данные счета в файле writeIIF.txt
find / i "% ($ OrderNumber)%" writeIIF.txt
echo errorlevel:% errorlevel%
if errorlevel 1 goto: HEADWRITE
if errorlevel 0 goto: LINEWRITE
: HEADWRITE
:: write Заголовок, отгрузка / обработка, скидка, данные о репутации и комиссии в файл импорта QB IIF
echo% ($ OrderNumber)%% ($ Purch_Date)% Invoice% ($ TransactionID)%% _QBAcct% Accounts Receivable% ($ Total)%% _Rep % >> writeIIF.txt
echo H / P% ($ Pack_Prep)% 1? >> writeIIF.txt
echo SHP% ($ Доставка)% 1? >> writeIIF.txt
echo DISC% ($ скидка)% 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
:: записывает цены со скидкой, проанализированные из пользовательской переменной:
echo% ($ ProductIdentifier) %% ($ Price_Each)%% ($ Quantity)%? >> writeIIF.txt
goto: EOF
: WRITE_DEFA
: записывает цены по умолчанию, полученные из данных о продукте
echo% ($ ProductIdentifier)%% ($ UnitPrice)%% ($ Quantity)%? >> writeIIF.txt
goto: EOF
:: 3-секундная задержка
:: TYPE NUL | CHOICE.COM / N / CY / TY, 3> NUL
: EOF

Bobb
источник
Не могли бы вы использовать для этого PowerShell? Я подозреваю, что вы получите немного больше контроля, если будете использовать PowerShell.
Роберт Харви,
1
Я проверил ваш командный файл - похоже, он работает нормально (после того, как я исправил строку «shift set ($ ProductIdentifier) ​​=% ~ 9» - которая, как мне кажется, является артефактом его копирования и вставки здесь).
atzz
Спасибо, Роберт Харви; Я смотрел PowerShell. Я не очень опытен в программировании .. не уверен, что будет походить на кривую обучения. У меня есть некоторый опыт работы с пакетными файлами, основная причина, по которой я выбрал это. Я собираюсь скомпилировать пакет, чтобы он работал быстрее. Спасибо за ответ.
BobB
Спасибо atzz: с тех пор я протестировал этот командный файл еще немного, и я достаточно уверен, что ~ тильда и изгоняющие кавычки не связаны с проблемой CMD с длинными именами путей. Я работал над этим, просто создавая подкаталог с коротким именем рядом с корнем, чтобы исключить длинные пути.
BobB
Нет необходимости показывать полный пакетный файл. Пожалуйста, сократите свой вопрос.
jor

Ответы:

193

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

Входные данные:

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

Г-н Рик
источник
Спасибо, это было то, что я искал SET BathFileAndPath=%~0(на самом деле, мой массив параметров начинается с 1, поэтому я использовалSET BathFileAndPath=%~1
Valamas
Можете объяснить, почему %widget:"=%избавляются от кавычек?
CodyBugstein
4
@Imray - :old=newэто сопоставление с образцом и замена в раскрытии переменной. При использовании "as the oldи ничего как the newкавычки удаляются, даже если они находятся посередине, даже если они не сбалансированы.
Джесси Чизхолм
set widget =% widget: "=% имеет странное поведение, когда виджет пустой, он возвращает" = "
Рахул Мисра
43

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

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

Например:

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

"%cmd%" %params%

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

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

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

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

set var=%var:"=%

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

echo "%var%"
t1ck
источник
Поначалу у меня тоже были проблемы с этим, оказалось, что я видел это :как .- после того, как разобрался, работал без сучка и задоринки. Отличный совет!
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". Следующий вопрос - как различать, существует ли "(двойная кавычка) или нет. Кому это может быть
интересно, заранее
3

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

Джон Кнеллер
источник
3

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

SET params = %~1

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

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

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

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


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

Завершающая кавычка "в строке 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"

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

CarryWise
источник
0
@echo off

Setlocal enabledelayedexpansion

Set 1=%1

Set 1=!1:"=!

Echo !1!

Echo "!1!"

Set 1=

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

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

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

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

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

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

Аарон Лоу
источник
0

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

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

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

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

установить "FirstName =% ~ 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%
user13490680
источник