Видалення подвійних лапок зі змінних у пакетному файлі створює проблеми із середовищем CMD


116

Чи може хтось допомогти ефективним та безпечним способом видалення цитат із пакетних змінних?

Я написав пакетний файл, який успішно імпортує список параметрів% 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 використовуються в іншому місці і не повинні включати лапки.

У тестовому пакетному файлі я мав успіх у усуненні лапок, використовуючи символ ~ 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....

Отже, може здатися, що додавання символу ~ tilde до змінних% 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) Моя «коротка та мила» ідея вставити ~ tilde у вхідні змінні% 1% 2 (% ~ 1 тощо), схоже, вплинула на деякі параметри та змінила спосіб переходу довгих імен шляхів до CMD.

2) Я все ще шукаю чистий і простий спосіб усунути цитати з вибраних названих змінних.

Будь-яка допомога для тих, хто досвідченіший, буде дуже вдячна. Я закінчую свої навички тут ... потрібні поради, будь ласка!

редагувати 26.12.2009 13:36 Весь пакетний файл PST:

Blockquote
:: dataout.bat
:: редакція 25.12.2009 додати ~ tilde до вхідних% змінних для усунення вбудованих "лапок.
:: записує список адрес, використовуючи параметри командного рядка
:: записує список вихідних даних для імпорту QBooks IIF
:: пише Дані замовлення продавця для RUI
:: зразок рядка командного рядка для тестування
:: listmail [ім'я] [прізвище] ["рядок адреси"] ["рядок міста"] [стан] [zip] [Порядок №] [PurchDate] [Регістр] ["FirstName LastName"] [TransactionID] [PaymentMethod] [Всього] [ProductID] [Кількість] [Price_Each] [PackPrep] [Доставка] [CommissionPmt] [Рахунок #]
:: приклад: dataout Bellewinkle Moose "123 Green Forest Way" "Vancouver" WA 98664 1004968 25.05.2009 "Bellewinkle Moose" "Olive Oyl" 101738 "На рахунку" 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 набір
змін
($ Кількість) =% ~ 9 набір
змін
($ Price_Each) =% ~ 9 набір
змін
($ Pack_Prep) =% ~ 9 набір
змін
($ Доставка) =% ~ 9 набір
змін
($ ServiceFee) =% ~ 9 набір
змін
($ знижка) =% ~ 9
зрушення
набір ($ Invoice) =% ~ 9
зсуву
безліч ($ UnitPrice) =% ~ 9
комплект _ShipCombName =% ($ FirstName) %% ($ LastName)%
відлуння ім'я комбо корабель% _ShipCombName%
пауза
:: записуйте рядкові змінні в файл
ехо FN% ($ FirstName)% LN% ($ LastName)% BA% ($ BillingAddress1)%% ($ BillingCity)%% ($ BillingState)%% ($ BillingPostal)%% ($ OrderNumber)%% ($ Purch_Date)%% ($ RegistrationName)%% ($ TransactionID)%% ($ PaymentMethod)%% ($ Total)%% ($ ProductIdentifier)%% ($ Кількість)%% ($ Price_Each) %% ($ Pack_Prep)%% ($ Доставка)%% ($ ServiceFee)%% ($ Знижка)%% ($ Рахунок)%% ($ UnitPrice)%% _ShipCombName% >> d_out_log.txt
:: Присвоїти рахунок Постачальник послуг
IF / i% ($ PaymentMethod)% == Дебіторська заборгованість Amazon SET _QBAcct = Amazon.com
:: 12-25-2009 додано другий вечірній метод Amazon для універсальності
IF / i% ($ PaymentMethod)% == SET Amazon _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 SET _Rep = Amazon
:: 12-25-2009 додано другий вечірній метод Amazon для універсальності
IF / i% ($ PaymentMethod)% == SET AmaR 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%
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 Файл адреси Написано
: ADDRFOUND
відібраний ехо- повтор % _Rep%
echo вибраний обліковий запис:% _QBAcct%
пауза
:: RUI OUT
:: записувати ID замовлення продавця & RUI Ідентифікатор замовлення на RUI
:: перевірити наявність дублікатів даних RUI 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
:: закінчення запису 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
ехо% ($ OrderNumber)%% ($ Purch_Date)% рахунок-фактура% ($ TransactionID)%% _QBAcct% Дебіторська заборгованість% ($ Всього)%% _Реп % >> writeIIF.txt
відлуння 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)% екв PH-1 goto WRITE_DEFA ELSE goto WRITE_DISC
echo% ($ ProductIdentifier)%
: WRITE_DISC
:: пише знижені ціни, розібрані зі спеціальної змінної:
echo% ($ ProductIdentifier) %% ($ Price_Each)%% ($ Кількість)%? >> writeIIF.txt
goto: EOF
: WRITE_DEFA
: пише ціни за замовчуванням, проаналізовані з даних про продукт
echo% ($ ProductIdentifier)%% ($ UnitPrice)%% ($ Кількість)%? >> writeIIF.txt
goto: EOF
:: 3 секундна затримка
:: TYPE NUL | CHOICE.COM / N / CY / TY, 3> NUL
: EOF


Чи можете ви використати PowerShell для цього? Я підозрюю, що ви отримаєте трохи більше контролю, якщо будете використовувати PowerShell.
Роберт Харві

1
Я перевірив ваш пакетний файл - він, здається, працює добре (після того, як я зафіксував рядок "set shift ($ ProductIdentifier) ​​=% ~ 9" - що, я думаю, є артефактом копіювання та вставлення тут).
atzz

Дякую Роберту Харві; Я дивився на PowerShell. Я не дуже досвід роботи з програмуванням .. не впевнений, якою буде крива навчання. У мене є досвід роботи з пакетними файлами, головна причина, по якій я вибрав саме це. Я маю намір скласти пакет, щоб він запустився швидше. Дякуємо за відповідь
BobB

Спасибі atzz: з тих пір я ще тестував цей пакетний файл, і я впевнений, що ~ tilde і виганяння котирувань не пов'язані з проблемою CMD w / long pathnames. Я вирішив це, просто встановивши короткий ім'я підкаталога, близький до кореня, щоб усунути довгі імена.
BobB

Не потрібно показувати повний пакетний файл. Скоротіть, будь ласка, своє запитання.
Джор

Відповіді:


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

Примітка. Щоб замінити слово "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
Валамас,

Чи можете ви пояснити, чому %widget:"=%позбавляється лапок?
CodyBugstein

4
@Imray - :old=newце відповідність шаблону та заміна в розширенні змінної. Що "стосується як oldі нічого, як то new, котирування видаляються, навіть якщо вони знаходяться посередині, навіть якщо вони не врівноважені.
Jesse Chisholm

set widget =% widget: "=% має дивну поведінку, коли віджет порожній, він повертається" = "
Rahul Misra

43

Ваш висновок (1) звучить неправильно. У грі повинен бути якийсь інший фактор.

Проблема лапок у параметрах пакетного файлу, як правило, вирішується шляхом видалення лапок, %~а потім повернення їх вручну, де це доречно.

Наприклад:

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

"%cmd%" %params%

Зверніть увагу на цитати навколо %cmd%. Без них шлях з пробілами не буде працювати.

Якщо ви можете опублікувати весь пакетний код, можливо, більш конкретну відповідь можна зробити.


1
Я згоден; мені здається, набір var =% ~ 1 повинен працювати добре. Я опублікую весь пакетний файл за запитом.
БобБ

Посилання MS: Використання пакетних параметрів . Хто знав, що існує стільки модифікаторів? Для довідки, офіційний MS MS дає опис %~1якExpands %1 and removes any surrounding quotation marks ("").
cod3monk3y

@ cod3monk3y Крім того, можна запитати cmdсебе про ці модифікатори: call /?про допомогу щодо модифікаторів параметрів, set /?для модифікаторів змінних (напевно, не дуже інтуїтивно). Досить зручно.
atzz

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 = Тестовий рядок". Наступне питання полягає в тому, як відрізнятись, чи існує "(подвійна цитата) чи ні.
Хто може стосуватись

3

Це здається простою помилкою, де ви використовуєте% ~ десь там, де ви не повинні бути. Використання, якщо% ~ принципово не змінює спосіб роботи пакетних файлів, воно просто видаляє лапки з рядка в тій самій ситуації.


3

Я дізнався за цим посиланням , якщо ви використовуєте XP або новішу версію, що це буде просто само собою:

SET params = %~1

Я не зміг отримати жодне з інших рішень тут для роботи на Windows 7.

Щоб перебрати їх, я зробив це:

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

Примітка. Ви отримаєте подвійні лапки лише в тому випадку, якщо введете аргументи, розділені пробілом.


0
  1. set 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: \ Документи та налаштування \ Адміністратор \ Мої документи \ Txt \ batchtest \ dataout.bat

повертає

'C: \ Документи' не розпізнається як внутрішня чи зовнішня команда ....

Тут уся ваша проблема. CMD не розуміє пробілів всередині імен файлів з командного рядка, тому вважає, що ви намагаєтеся пройти

і Налаштування \ Адміністратор \ Мої документи \ Txt \ batchtest \ dataout.bat

як параметри до

"C: \ Документи"

програма.

Вам потрібно процитувати його, щоб запустити пакетний файл з пробілами на шляху:

> "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' == '', перейдіть на ваш номер

Але якщо перевірка наявності файлу, який може мати, а може і не мати лапки, то це:

Якщо існує "! 1!" goto othersub

Зауважте, використання одиничних і подвійних лапок є різними.


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%
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.