Remover aspas duplas de variáveis ​​no arquivo em lote cria problemas com o ambiente CMD

116

Alguém pode ajudar com uma maneira eficaz e segura de remover cotações de variáveis ​​de lote?

Eu escrevi um arquivo em lote que importa com sucesso uma lista de parâmetros% 1,% 2,% 3 etc. e os coloca em variáveis ​​nomeadas. Alguns desses parâmetros contêm várias palavras e, portanto, estão entre aspas duplas.

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

Essas% variáveis ​​são colocadas em seguida nas variáveis ​​nomeadas:

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

a verificação das variáveis ​​é feita por echo.

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

resultados exibidos como

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

Preciso eliminar as cotações incluídas nas variáveis ​​selecionadas. Por exemplo, FirstName e LastName são usados ​​em outro lugar e não devem incluir aspas.

Em um arquivo de lote de teste, consegui eliminar as aspas usando o caractere ~ til nas variáveis.

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

Achei que tinha a solução, mas logo experimentei um comportamento incomum com a execução de arquivos em lote. De repente, o CMD deixa de reconhecer as declarações de longo caminho. Execução normal de arquivo em lote do caminho completo

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

retorna

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

Portanto, parece que a adição do caractere ~ tilde às variáveis% 1% 2 ...% n de entrada causou alguma mudança. Possivelmente algumas variáveis ​​de ambiente foram alteradas?

Também tentei limpar aspas de dentro da variável com várias tentativas usando o comando FOR. Isso parece estranho e não consegui aprender como fazer isso criando uma lista de variáveis ​​para realizar a tarefa:

algo assim:

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

Acho que tenho dois problemas.

1) Minha ideia 'curta e doce' de inserir ~ til nas variáveis ​​de entrada% 1% 2 (% ~ 1, etc) parece ter afetado algumas configurações e alterado como o CMD navega por nomes de caminho longos.

2) Ainda estou em busca de uma maneira limpa e fácil de eliminar aspas de variáveis ​​nomeadas selecionadas.

Qualquer ajuda para os mais experientes seria muito apreciada. Estou no fim das minhas habilidades aqui ... preciso de uma orientação por favor!

editar arquivo de lote inteiro de 26/12/2009 13:36 PST:

Blockquote
:: dataout.bat
:: revisão 25/12/2009 adiciona ~ til às variáveis% de entrada para eliminar "aspas embutidas.
:: grava a lista de endereços usando parâmetros de linha de comando
:: grava a lista de saída de dados para QBooks IIF import
:: grava Dados do pedido do comerciante para RUI
:: amostra de string de linha de comando para teste
:: listmail [nome] [sobrenome] ["string de endereço"] ["string de cidade"] [estado] [zip] [Pedido #] [PurchDate] [Regname] ["FirstName LastName"] [TransactionID] [PaymentMethod] [Total] [ProductID] [Qty] [Price_Each] [PackPrep] [Shipping] [CommissionPmt] [Invoice #]
:: exemplo: 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 documentos e configurações \ administrador \ meus documentos \ txt \ batchtest
processamento de eco% 1% 2
: VARISET
::Converter% n parâmetros de linha de comando em variáveis ​​de string
definidas ($ FirstName) =% ~ 1
conjunto ($ LastName) =% ~ 2
conjunto ($ BillingAddress1) =% ~ 3
conjunto ($ BillingCity) =% ~ 4
conjunto ($ BillingState) =% ~ 5
set ($ BillingPostal) =% ~ 6
set ($ OrderNumber) =% ~ 7
set ($ Purch_Date) =% ~ 8
set ($ RegistrationName) =% ~ 9

conjunto de turnos ($ TransactionID) = conjunto de
turnos % ~ 9
($ PaymentMethod) = conjunto de
turnos % ~ 9
($ Total) =
conjunto de turnos % ~ 9 ($ ProductIdentifier) ​​= conjunto de
turnos % ~ 9
($ Quantity) =% ~ 9 conjunto de
turnos
($ Price_Each) = conjunto de
turnos % ~ 9
($ Pack_Prep) = conjunto de
turnos % ~ 9
($ Shipping) = conjunto de
turnos % ~ 9
($ ServiceFee) = conjunto de
turnos % ~ 9
($ Desconto) =% ~ 9
shift
set ($ Invoice) =% ~ 9
shift
set ($ UnitPrice) =% ~ 9
set _ShipCombName =% ($ FirstName)%% ($ LastName)%
echo ship combo name is% _ShipCombName%
pause
:: escrever string varibables no arquivo de log
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
:: Atribuir conta por Provedor de serviços
IF / i% ($ PaymentMethod)% == Amazon Receivables SET _QBAcct = Amazon.com
:: 12-25-2009 adicionado segundo método Amazon pm't para versatilidade
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 conta 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
:: Atribuir designador de representante baseado em QBAccount
IF / i% ($ PaymentMethod)% == Amazon Receivables SET _Rep = Amazon
:: 12-25-2009 adicionado segundo método Amazon pm't para versatilidade
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 conta SET _Rep = RB
IF / i% ($ PaymentMethod)% == Mail SET _Rep = RB
IF / i% ($ PaymentMethod)% == AMER SET _Rep = BlueZap
IF / i % ($ PaymentMethod)% == DISC SET _Rep = BlueZap
:: verificar se há dados de endereço duplicados
findstr / i / s "% _ShipCombName%" addrlist.txt
echo errorlevel:% errorlevel%
se errorlevel 1 goto: ADDRWRITE
se 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 account selected is:% _QBAcct%
pause
:: RUI OUT
:: Write Merchant Order ID & RUI Order ID to RUI
:: Check for duplicate RUI data em writeRUI.txt
cd ..
cd RegKOut
find / i "% ($ OrderNumber)%" writeRUI.txt
echo errorlevel:% errorlevel%
se errorlevel % if errorlevel 1 goto: RUIWRITE
if errorlevel 0 goto: IIFWRITE
: RUIWRITE
echo% ($ Invoice)% % ($ OrderNumber)% >> writeRUI.txt
:: end write RUI
:: IIF OUT
: IIFWRITE
:: Verifique se há dados de fatura duplicados em writeIIF.txt
find / i "% ($ OrderNumber)%" writeIIF.txt
echo errorlevel:% errorlevel%
se errorlevel 1 goto: HEADWRITE
se errorlevel 0 goto: LINEWRITE
: HEADWRITE
:: write Dados de cabeçalho, envio / manuseio, desconto, Rep & comissão para arquivo de importação QB IIF
echo% ($ OrderNumber)%% ($ Purch_Date)% Invoice% ($ TransactionID)%% _QBAcct% Contas a Receber% ($ Total)% _Rep % >> writeIIF.txt
echo H / P% ($ Pack_Prep)% 1? >> writeIIF.txt
echo SHP% ($ Shipping)% 1? >> writeIIF.txt
echo DISC% ($ Desconto)% 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
:: grava preços com desconto analisados ​​a partir da variável personalizada:
echo% ($ ProductIdentifier) %% ($ Price_Each)%% ($ Quantity)%? >> writeIIF.txt
goto: EOF
: WRITE_DEFA
: grava os preços padrão analisados ​​a partir dos dados do produto
echo% ($ ProductIdentifier)%% ($ UnitPrice)%% ($ Quantity)%? >> writeIIF.txt
goto: EOF
:: 3 segundos de atraso
:: TYPE NUL | CHOICE.COM / N / CY / TY, 3> NUL
: EOF

BobB
fonte
Você poderia usar o PowerShell para fazer isso? Suspeito que você terá um pouco mais de controle se usar o PowerShell.
Robert Harvey
1
Verifiquei seu arquivo em lote - parece funcionar bem (depois de corrigir a linha "shift set ($ ProductIdentifier) ​​=% ~ 9" - que, creio eu, é um artefato de copiar e colar aqui).
atzz
Obrigado, Robert Harvey; Tenho olhado para o PowerShell. Não tenho muita experiência c / programação .. não tenho certeza de como seria a curva de aprendizado. Eu tenho alguma experiência com arquivos em lote, principal razão pela qual escolhi isso. Pretendo compilar o lote para que seja executado mais rápido. Obrigado pela resposta.
BobB
Obrigado atzz: Eu testei este arquivo em lote um pouco mais e estou razoavelmente confiante de que o ~ til e as citações de banimento não estão relacionados ao problema de CMD com nomes de caminho longos. Eu resolvi isso apenas configurando um subdiretório de nome curto próximo à raiz para eliminar nomes de caminho longos.
BobB
Não há necessidade de mostrar o arquivo de lote completo. Reduza a sua pergunta.
jor

Respostas:

192

Você tem uma aspa dupla extra no final, que a adiciona de volta ao final da string (após remover ambas as aspas da string).

Entrada:

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

Resultado:

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

Nota: Para substituir aspas duplas "por aspas simples", faça o seguinte:

set widget=%widget:"='%

Observação: para substituir a palavra "Mundo" (sem distinção entre maiúsculas e minúsculas) por BobB, faça o seguinte:

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

Resultado:

widget="Hello BobB!"

No que diz respeito à sua pergunta inicial (salve o seguinte código em um arquivo em lote .cmd ou .bat e execute):

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

Resultado:

"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é o nome e o caminho do script.
%1é o primeiro argumento da linha de comando e assim por diante.

Sr. Rick
fonte
Obrigado, era isso que eu SET BathFileAndPath=%~0SET BathFileAndPath=%~1
procurava
Você pode explicar por que %widget:"=%se livrar das aspas?
CodyBugstein
4
@Imray - :old=newé uma correspondência e substituição de padrão na expansão da variável. Com "as olde nada como as new, as aspas são removidas, mesmo que estejam no meio, mesmo que estejam desequilibradas.
Jesse Chisholm
set widget =% widget: "=% tem um comportamento estranho quando o widget está em branco, ele retorna" = "
Rahul Misra
43

Sua conclusão (1) parece errada. Deve haver algum outro fator em jogo.

O problema das cotações nos parâmetros do arquivo em lote é normalmente resolvido removendo as cotações com %~e, em seguida, colocando-as de volta manualmente quando apropriado.

Por exemplo:

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

"%cmd%" %params%

Observe as citações ao redor %cmd%. Sem eles, o caminho com espaços não funcionará.

Se você pudesse postar seu código de lote inteiro, talvez uma resposta mais específica pudesse ser feita.

Atzz
fonte
1
Eu concordo; parece-me que o conjunto var =% ~ 1 deve funcionar bem. Vou postar o arquivo de lote inteiro conforme solicitado.
BobB
Referência MS: Usando parâmetros de lote . Quem diria que havia tantos modificadores? Para referência, o documento oficial do MS fornece a descrição de %~1asExpands %1 and removes any surrounding quotation marks ("").
cod3monk3y
@ cod3monk3y Além disso, é possível questionar- cmdse sobre esses modificadores: call /?para obter ajuda sobre modificadores de parâmetros, set /?para modificadores de variáveis ​​(provavelmente não muito intuitivos). Muito prático.
atzz
12

Normalmente, apenas removo todas as aspas de minhas variáveis ​​com:

set var=%var:"=%

E depois aplique-os novamente onde eu precisar, por exemplo:

echo "%var%"
t1ck
fonte
Eu também tive problemas com isso no início, descobri que estava vendo o :como um .- depois de descobrir isso, funcionava sem problemas. Ótima dica!
DaveU
9

Gastou muito tempo tentando fazer isso de uma maneira simples. Depois de examinar cuidadosamente o loop FOR, percebi que posso fazer isso com apenas uma linha de código:

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

Exemplo:

@ECHO OFF
SET Quoted="Test string"

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

ECHO %Quoted%
ECHO %Unquoted%

Resultado:

"Test string"
Test string
Vitaliy Ulantikov
fonte
Este método não é relevante enquanto "SET Quoted = Test string". A próxima pergunta é como diferir "(aspas) existe ou não. A quem possa interessar, obrigado desde já.
Rhak Kahr
3

Isso soa como um bug simples onde você está usando% ~ em algum lugar onde não deveria estar. O uso se% ~ não altera fundamentalmente a maneira como os arquivos em lote funcionam, apenas remove as aspas da string nessa única situação.

John Knoeller
fonte
3

Aprendi neste link , se você estiver usando XP ou superior, que isso simplesmente funcionará por si só:

SET params = %~1

Não consegui que nenhuma das outras soluções aqui funcionasse no Windows 7.

Para iterar sobre eles, fiz o seguinte:

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

Nota: Você só obterá aspas duplas se passar argumentos normalmente separados por um espaço.


fonte
0
  1. set widget = "um item muito útil"
  2. definir widget
  3. widget = "um item muito útil"
  4. definir widget =% widget: "=%"
  5. definir widget
  6. definir widget = um item muito útil "

A citação final "na linha 4 adiciona uma citação "à string. Deve ser removido. A sintaxe da linha 4 termina com%

David
fonte
@ user195488 - leia a linha 3 conforme observe que ela é exibida:widget="a very useful item" e leia a linha 6 conforme observe que ela é exibida:widget=a very useful item" e entenda que a linha 7 seria set widget=%widget:"=%e a linha 8 seria observada que a linha exibida widget=a very useful itemnão tem mais uma aspa final .
Jesse Chisholm
0

Achei que tinha a solução, mas logo experimentei um comportamento incomum com a execução de arquivos em lote. De repente, o CMD deixa de reconhecer as declarações de longo caminho. Execução normal de arquivo em lote do caminho completo

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

retorna

'C: \ Documentos' não é reconhecido como um comando interno ou externo ....

Aí está todo o seu problema. O CMD não entende os espaços dentro dos nomes dos arquivos da linha de comando, então pensa que você está tentando passar

e Configurações \ Administrador \ Meus Documentos \ Txt \ batchtest \ dataout.bat

como parâmetros para o

"C: \ Documentos"

programa.

Você precisa citá-lo para executar um arquivo em lote com espaços no caminho:

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

teria funcionado.

CarryWise
fonte
0
@echo off

Setlocal enabledelayedexpansion

Set 1=%1

Set 1=!1:"=!

Echo !1!

Echo "!1!"

Set 1=

Demonstra com ou sem aspas, independentemente de o parâmetro original ter aspas ou não.

E se você quiser testar a existência de um parâmetro que pode ou não estar entre aspas, coloque esta linha antes dos ecos acima:

Se '% 1' == '' ir para seuub

Mas se estiver verificando a existência de um arquivo que pode ou não ter aspas, então é:

Se EXISTIR "! 1!" ir para outro sub

Observe que o uso de aspas simples e aspas duplas são diferentes.

Aaron Lowe
fonte
0

Todas as respostas estão completas. Mas queria acrescentar uma coisa,

definir FirstName =% ~ 1

definir LastName =% ~ 2

Esta linha deveria ter funcionado, você precisava de uma pequena mudança.

definir "FirstName =% ~ 1"

definir "LastName =% ~ 2"

Inclua a tarefa completa entre aspas. Isso removerá aspas sem problemas. Esta é uma forma preferida de atribuição que corrige problemas indesejados com aspas nos argumentos.

Codinome Jack
fonte
0

A sintaxe til simples funciona apenas para remover aspas em torno dos parâmetros de linha de comando que estão sendo passados ​​para os arquivos em lote

SET xyz=%~1

O código do arquivo em lote acima definirá xyz para qualquer valor que esteja sendo passado como primeiro parâmetro, removendo as citações iniciais e finais (se houver).

Mas, esta sintaxe simples de til não funcionará para outras variáveis ​​que não foram passadas como parâmetros

Para todas as outras variáveis, você precisa usar a sintaxe de substituição expandida que requer que você especifique os caracteres iniciais e finais a serem removidos. Efetivamente, estamos instruindo para remover o primeiro e o último caractere sem olhar para o que ele realmente é.

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

Se quisermos verificar o que o primeiro e o último caractere eram realmente aspas antes de removê-lo, precisaremos de algum código extra como segue

@SET VAR="Some Very Long Quoted String"
If aa%VAR:~0,1%%VAR:~-1%aa == aa""aa SET UNQUOTEDVAR=%VAR:~1,-1%
user13490680
fonte