Usunięcie cudzysłowów ze zmiennych w pliku wsadowym powoduje problemy ze środowiskiem CMD

116

Czy ktoś może pomóc w skutecznym i bezpiecznym sposobie usuwania cudzysłowów ze zmiennych wsadowych?

Napisałem plik wsadowy, który pomyślnie importuje listę parametrów% 1,% 2,% 3 itd. I umieszcza je w nazwanych zmiennych. Niektóre z tych parametrów zawierają wiele słów i dlatego są ujęte w podwójne cudzysłowy.

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

Te% zmiennych są następnie umieszczane w nazwanych zmiennych:

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

weryfikacja zmiennych odbywa się za pomocą echa.

echo.% FirstName%
echo.% LastName%
echo.% ShipAddr%

wyniki są wyświetlane jako

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

Muszę wyeliminować zawarte cytaty z wybranych zmiennych. Na przykład imię i nazwisko są używane w innych miejscach i nie mogą zawierać cudzysłowów.

W testowym pliku wsadowym udało mi się wyeliminować cudzysłowy przy użyciu znaku ~ tyldy w zmiennych.

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

Myślałem, że mam rozwiązanie, ale wkrótce doświadczyłem niezwykłego zachowania podczas wykonywania plików wsadowych. Nagle CMD nie rozpoznaje instrukcji długiej ścieżki. Normalne wykonanie pliku wsadowego z pełnej ścieżki

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

zwroty

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

Wygląda więc na to, że dodanie znaku ~ tyldy do nadchodzących zmiennych% 1% 2 ...% n spowodowało pewną zmianę. Być może niektóre zmienne środowiskowe zostały zmienione?

Próbowałem też wyczyścić cudzysłowy z wewnątrz zmiennej przy różnych próbach za pomocą polecenia FOR. Wydaje się to niezręczne i nie mogłem się nauczyć, jak to zrobić, tworząc listę zmiennych do wykonania zadania:

coś takiego:

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

Myślę, że mam dwa problemy.

1) Mój „krótki i słodki” pomysł wstawiania ~ tyldy w przychodzących zmiennych% 1% 2 (% ~ 1, itd.) Wydaje się mieć wpływ na niektóre ustawienia i zmienił sposób nawigacji CMD w długich nazwach ścieżek.

2) Nadal szukam czystego i łatwego sposobu na wyeliminowanie cudzysłowów z wybranych nazwanych zmiennych.

Jakakolwiek pomoc dla bardziej doświadczonych byłaby bardzo mile widziana. Moje umiejętności dobiegły końca ... proszę o wskazówki!

edytuj 12/26/2009 13:36 PST cały plik wsadowy:

Blockquote
:: dataout.bat
:: rewizja 25.12.2009 add ~ tylda przychodzących% zmiennych, aby wyeliminować osadzone „w cudzysłowie.
:: pisze listy adresów za pomocą parametrów wiersza poleceń
:: pisze listy Wyjście danych dla QBooks IIF importowych
:: zapisów Dane zamówienia sprzedawcy dla RUI
:: przykładowy ciąg wiersza poleceń do testowania
:: listmail [imię] [nazwisko] ["ciąg adresu"] ["ciąg miasta"] [stan] [zip] [nr zamówienia] [data zakupu] [nazwa rejestracji] ["FirstName LastName"] [TransactionID] [PaymentMethod] [Total] [ProductID] [Qty] [Price_Each] [PackPrep] [Shipping] [CommissionPmt] [Invoice #]
:: przykład: dataout Łoś Bellewinkle "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 dokumenty i ustawienia \ administrator \ moje dokumenty \ txt \ batchtest
przetwarzanie echo% 1% 2
: VARISET
::Konwertuj parametry wiersza poleceń% n na
zestaw zmiennych łańcuchowych ($ FirstName) =
zestaw % ~ 1 ($ LastName) =
zestaw % ~ 2 ($ BillingAddress1) =
zestaw % ~ 3 ($ BillingCity) =
zestaw % ~ 4 ($ BillingState) =
Zestaw % ~ 5 ($ BillingPostal) =
Zestaw % ~ 6 ($ OrderNumber) =
Zestaw % ~ 7 ($ Purch_Date) =
Zestaw % ~ 8 ($ RegistrationName) =% ~ 9

zestaw zmian ($ TransactionID) = zestaw
zmian % ~ 9
($ PaymentMethod) = zestaw
zmian % ~ 9
($ Total) =
zestaw zmian % ~ 9 ($ ProductIdentifier) ​​= zestaw
zmian % ~ 9
($ Quantity) =% ~ 9 zestaw
zmian
($ Price_Each) =% ~ 9 zestaw
zmian
($ Pack_Prep) =% ~ 9 zestaw
zmian
($ Shipping) =% ~ 9 zestaw
zmian
($ ServiceFee) =% ~ 9 zestaw
zmian
($ Rabat) =% ~ 9 zestaw
zmian
($ Invoice) =% ~ 9 zestaw
zmian
($ UnitPrice) =% ~ 9
zestaw _ShipCombName =% ($ FirstName)%% ($ LastName)%
echo nazwa kombinacji statku to% _ShipCombName%
pauza
:: zapisz zmienne łańcuchowe do pliku dziennika
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)%% ($ Rabat)%% ($ Invoice)%% ($ UnitPrice)%% _ShipCombName% >> d_out_log.txt
:: Przypisz konto przez Usługodawca
IF / i% ($ PaymentMethod)% == Amazon Receivables SET _QBAcct = Amazon.com
:: 12-25-2009 dodano drugą metodę Amazon pm't dla wszechstronności
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)% == Na koncie 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 desygnator na podstawie QBAccount
IF / i% ($ PaymentMethod)% == Należności Amazon SET _Rep = Amazon
:: 12-25-2009 dodano drugą metodę Amazon pm't dla wszechstronności
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)% == Na koncie SET _Rep = RB
IF / i% ($ PaymentMethod)% == Mail SET _Rep = RB
IF / i% ($ PaymentMethod)% == AMER SET _Rep = BlueZap
IF / i % ($ PaymentMethod)% == ZESTAW DYSKÓW _Rep = BlueZap
:: sprawdź, czy nie ma zduplikowanych danych adresowych
findstr / i / s "% _ShipCombName%" addrlist.txt
echo errorlevel:% errorlevel%
jeśli errorlevel 1 goto: ADDRWRITE
jeśli errorlevel 0 goto: ADDRFOUND
: ADDRWRITE
echo% _ShipCombName% >> addrlist.txt
echo% ($ BillingAddress1)% >> addrlist.txt
echo% ($ BillingCity)%% ($ BillingState)%% ($ BillingPostal)% >> addrlist.txt
echo. >> addrlist.txt
echo Zapisany plik adresu
: ADDRFOUND
echo wybrany rep to% _Rep%
echo wybrane konto to:% _QBAcct%
pause
:: RUI OUT
:: zapis ID zamówienia sprzedawcy i ID zamówienia RUI do RUI
:: sprawdź, czy nie ma zduplikowanych danych 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
:: end write RUI
:: IIF OUT
: IIFWRITE
:: Sprawdź zduplikowane dane faktury w writeIIF.txt
find / i "% ($ OrderNumber)%" writeIIF.txt
echo errorlevel:% errorlevel%
jeśli errorlevel 1 goto: HEADWRITE
jeśli errorlevel 0 goto: LINEWRITE
: HEADWRITE
:: write Nagłówek, wysyłka / obsługa, rabat, dane rep i prowizji do QB IIF import pliku
echo% ($ OrderNumber)%% ($ Purch_Date)% Faktura% ($ TransactionID)%% _QBAcct% Rozrachunki do otrzymania% ($ Razem)%% _Rep % >> writeIIF.txt
echo H / P% ($ Pack_Prep)% 1? >> writeIIF.txt
echo SHP% ($ Wysyłka)% 1? >> writeIIF.txt
echo DISC% ($ Rabat)% 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
:: zapisuje obniżone ceny przeanalizowane ze zmiennej niestandardowej:
echo% ($ ProductIdentifier) %% ($ Price_Each)%% ($ Quantity)%? >> writeIIF.txt
goto: EOF
: WRITE_DEFA
: zapisuje ceny domyślne przeanalizowane z danych produktu
echo% ($ ProductIdentifier)%% ($ UnitPrice)%% ($ Quantity)%? >> writeIIF.txt
goto: EOF
:: 3-sekundowe opóźnienie
:: TYPE NUL | CHOICE.COM / N / CY / TY, 3> NUL
: EOF

BobB
źródło
Czy mógłbyś użyć do tego PowerShell? Podejrzewam, że uzyskasz trochę większą kontrolę, jeśli użyjesz PowerShell.
Robert Harvey
1
Sprawdziłem twój plik wsadowy - wygląda na to, że działa dobrze (po naprawieniu linii "shift set ($ ProductIdentifier) ​​=% ~ 9" - co, jak sądzę, jest artefaktem kopiowania i wklejania go tutaj).
atzz
Dziękuję Robert Harvey; Patrzyłem na PowerShell. Nie mam dużego doświadczenia w programowaniu… nie jestem pewien, jaka byłaby krzywa uczenia się. Mam pewne doświadczenie z plikami wsadowymi, główny powód, dla którego wybrałem to. Zamierzam skompilować pakiet, aby działał szybciej. Dzięki za odpowiedź.
BobB
Dzięki atzz: Od tego czasu przetestowałem ten plik wsadowy trochę więcej i jestem dość pewny, że cytaty ~ tyldy i banujące cudzysłowy nie mają związku z problemem CMD z długimi nazwami ścieżek. Obejrzałem to, ustawiając podkatalog o krótkiej nazwie blisko katalogu głównego, aby wyeliminować długie nazwy ścieżek.
BobB
Nie ma potrzeby pokazywania pełnego pliku wsadowego. Skróć pytanie.
jor

Odpowiedzi:

192

Na końcu znajduje się dodatkowy podwójny cudzysłów, czyli dodanie go z powrotem na końcu ciągu (po usunięciu obu cudzysłowów z ciągu).

Wejście:

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

Wynik:

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

Uwaga: Aby zamienić podwójne cudzysłowy „na pojedyncze cudzysłowy”, wykonaj następujące czynności:

set widget=%widget:"='%

Uwaga: aby zamienić słowo „Świat” (bez rozróżniania wielkości liter) na BobB, wykonaj następujące czynności:

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

Wynik:

widget="Hello BobB!"

Jeśli chodzi o twoje pierwsze pytanie (zapisz następujący kod w pliku wsadowym .cmd lub .bat i uruchom):

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

Wynik:

"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 . . .

%0to nazwa i ścieżka skryptu.
%1jest pierwszym argumentem wiersza poleceń i tak dalej.

Panie Rick
źródło
Dzięki, o to mi chodziło SET BathFileAndPath=%~0(w rzeczywistości moja tablica parametrów zaczyna się od 1, więc użyłemSET BathFileAndPath=%~1
Valamas
Czy możesz wyjaśnić, dlaczego %widget:"=%pozbywa się cudzysłowów?
CodyBugstein,
4
@Imray - :old=newjest to dopasowanie i zamiana wzorca w rozwijaniu zmiennych. Gdy "the oldi nic jako the new, cudzysłowy są usuwane, nawet jeśli znajdują się pośrodku, nawet jeśli są niezrównoważone.
Jesse Chisholm
set widget =% widget: "=% zachowuje się dziwnie, gdy widget jest pusty, zwraca" = "
Rahul Misra
43

Twój wniosek (1) brzmi źle. W grę musi wchodzić jakiś inny czynnik.

Problem cudzysłowów w parametrach pliku wsadowego jest zwykle rozwiązywany przez usunięcie cudzysłowów za pomocą, %~a następnie w razie potrzeby ręczne umieszczenie ich z powrotem.

Na przykład:

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

"%cmd%" %params%

Zwróć uwagę na cytaty wokół %cmd%. Bez nich ścieżka ze spacjami nie zadziała.

Gdybyś mógł opublikować cały kod partii, być może można by udzielić bardziej szczegółowej odpowiedzi.

atzz
źródło
1
Zgadzam się; wydaje mi się, że zestaw var =% ~ 1 powinien działać dobrze. Na żądanie wyślę cały plik wsadowy.
BobB
Referencje MS: Używanie parametrów partii . Kto wiedział, że jest tak wiele modyfikatorów? Dla porównania, oficjalny dokument MS zawiera opis %~1asExpands %1 and removes any surrounding quotation marks ("").
cod3monk3y
@ cod3monk3y Można również zadać cmdsobie pytanie o te modyfikatory: call /?o pomoc dotyczącą modyfikatorów parametrów, set /?o modyfikatory zmiennych (prawdopodobnie niezbyt intuicyjne). Całkiem przydatne.
atzz
12

Zwykle po prostu usuwam wszystkie cudzysłowy z moich zmiennych za pomocą:

set var=%var:"=%

A potem zastosuj je ponownie tam, gdzie ich potrzebuję np:

echo "%var%"
t1ck
źródło
Na początku też miałem z tym problem, okazało się, że widzę to :jako .- po zorientowaniu się, działało bez problemu. Świetna wskazówka!
DaveU
9

Spędziłem dużo czasu, próbując to zrobić w prosty sposób. Po uważnym przyjrzeniu się pętli FOR zdałem sobie sprawę, że mogę to zrobić za pomocą tylko jednej linii kodu:

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

Przykład:

@ECHO OFF
SET Quoted="Test string"

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

ECHO %Quoted%
ECHO %Unquoted%

Wynik:

"Test string"
Test string
Vitaliy Ulantikov
źródło
Ta metoda nie ma zastosowania, gdy „SET Quoted = Test string”. Kolejne pytanie brzmi: jak się od siebie różnić "(podwójny cudzysłów) istnieje, czy nie. Komu zainteresowanemu, z góry dziękuję.
Rhak Kahr
3

To brzmi jak zwykły błąd, w którym używasz% ~ gdzieś, gdzie nie powinieneś. Użycie, jeśli% ~ nie zmienia zasadniczo sposobu działania plików wsadowych, po prostu usuwa cudzysłowy z ciągu w tej pojedynczej sytuacji.

John Knoeller
źródło
3

Dowiedziałem się z tego linku , jeśli używasz XP lub nowszego, że to po prostu zadziała samo:

SET params = %~1

Nie udało mi się uzyskać żadnego innego rozwiązania do pracy w systemie Windows 7.

Aby je powtórzyć, zrobiłem to:

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

Uwaga: Podwójne cudzysłowy otrzymasz tylko wtedy, gdy zwykle przekażesz argumenty oddzielone spacją.


źródło
0
  1. ustaw widget = "bardzo przydatny przedmiot"
  2. ustaw widżet
  3. widget = "bardzo przydatny przedmiot"
  4. ustaw widget =% widget: "=%"
  5. ustaw widżet
  6. ustaw widget = bardzo przydatny przedmiot "

Cudzysłów na końcu "linii 4 dodaje cudzysłów "do ciągu. Powinien zostać usunięty. Składnia linii 4 kończy się na%

David
źródło
@ user195488 - przeczytaj wiersz 3, obserwując, że został wyświetlony:widget="a very useful item" i przeczytaj wiersz 6, ponieważ został wyświetlony:widget=a very useful item" i zrozum, że wiersz 7 byłby, set widget=%widget:"=%a wiersz 8 byłby zauważony, że wyświetlana linia widget=a very useful itemnie ma już końcowego cudzysłowu .
Jesse Chisholm
0

Myślałem, że mam rozwiązanie, ale wkrótce doświadczyłem niezwykłego zachowania podczas wykonywania plików wsadowych. Nagle CMD nie rozpoznaje instrukcji długiej ścieżki. Normalne wykonanie pliku wsadowego z pełnej ścieżki

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

zwroty

„C: \ Dokumenty” nie jest rozpoznawane jako polecenie wewnętrzne lub zewnętrzne ....

To cały twój problem. CMD nie rozumie spacji w nazwach plików z wiersza poleceń, więc myśli, że próbujesz przekazać

i Ustawienia \ Administrator \ Moje dokumenty \ Txt \ batchtest \ dataout.bat

jako parametry do

„C: \ Dokumenty”

program.

Musisz go zacytować, aby uruchomić plik wsadowy ze spacjami w ścieżce:

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

zadziałałoby.

CarryWise
źródło
0
@echo off

Setlocal enabledelayedexpansion

Set 1=%1

Set 1=!1:"=!

Echo !1!

Echo "!1!"

Set 1=

Pokazuje z cudzysłowami lub bez nich, niezależnie od tego, czy oryginalny parametr zawiera cudzysłowy, czy nie.

A jeśli chcesz sprawdzić istnienie parametru, który może, ale nie musi być w cudzysłowach, umieść tę linię przed powyższym echem:

Jeśli '% 1' == '' goto yoursub

Ale jeśli sprawdzasz, czy istnieje plik, który może zawierać cudzysłowy lub nie, to jest to:

Jeśli ISTNIEJE "! 1!" goto othersub

Zwróć uwagę, że użycie apostrofów i cudzysłowów jest różne.

Aaron Lowe
źródło
0

Wszystkie odpowiedzi są kompletne. Ale chciałem dodać jedną rzecz,

ustaw FirstName =% ~ 1

ustaw LastName =% ~ 2

Ta linia powinna zadziałać, potrzebowałeś małej zmiany.

ustaw „FirstName =% ~ 1”

ustaw „LastName =% ~ 2”

Uwzględnij całe zadanie w cudzysłowie. Usunie cytaty bez problemu. Jest to preferowany sposób przypisywania, który rozwiązuje niechciane problemy za pomocą cudzysłowów w argumentach.

Imię Jack
źródło
0

Prosta składnia tyldy działa tylko przy usuwaniu cudzysłowów wokół parametrów wiersza poleceń przekazywanych do plików wsadowych

SET xyz=%~1

Powyższy kod pliku wsadowego ustawi xyz na dowolną wartość przekazywaną jako pierwszy parametr usuwając początkowe i końcowe cudzysłowy (jeśli są obecne).

Ale ta prosta składnia tyldy nie będzie działać dla innych zmiennych, które nie zostały przekazane jako parametry

W przypadku wszystkich innych zmiennych należy użyć rozszerzonej składni podstawiania, która wymaga określenia wiodących i opóźnionych znaków, które mają zostać usunięte. Skutecznie instruujemy, aby usunąć pierwszy i ostatni znak bez patrzenia na to, co to jest.

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

Jeśli chcemy sprawdzić, jaki właściwie był pierwszy i ostatni znak cudzysłowu przed jego usunięciem, będziemy potrzebować dodatkowego kodu, jak poniżej

@SET VAR="Some Very Long Quoted String"
If aa%VAR:~0,1%%VAR:~-1%aa == aa""aa SET UNQUOTEDVAR=%VAR:~1,-1%
user13490680
źródło