Eliminar las comillas dobles de las variables en el archivo por lotes crea problemas con el entorno CMD

116

¿Alguien puede ayudar con una forma eficaz y segura de eliminar las cotizaciones de las variables de lote?

He escrito un archivo por lotes que importa con éxito una lista de parámetros% 1,% 2,% 3, etc. y los coloca en variables con nombre. Algunos de estos parámetros contienen varias palabras y, por lo tanto, se incluyen entre comillas dobles.

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

Estas% variables se colocan a continuación en variables con nombre:

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

La verificación de las variables se realiza mediante eco.

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

los resultados se muestran como

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

Necesito eliminar las comillas incluidas en las variables seleccionadas. Por ejemplo, FirstName y LastName se utilizan en otros lugares y no deben incluir comillas.

En un archivo por lotes de prueba, logré eliminar las comillas usando el carácter ~ tilde en las variables.

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

Pensé que tenía la solución, pero pronto experimenté un comportamiento inusual con la ejecución de archivos por lotes. De repente, CMD no reconoce declaraciones de largo recorrido. Ejecución normal del archivo por lotes desde la ruta completa

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

devoluciones

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

Por tanto, parece que la adición del carácter ~ tilde a las variables% 1% 2 ...% n entrantes ha provocado algún cambio. ¿Posiblemente se hayan alterado algunas variables de entorno?

También intenté borrar las comillas desde dentro de la variable con varios intentos usando el comando FOR. Eso parece incómodo y no he podido aprender cómo lograr esto creando una lista de variables para realizar la tarea:

algo como esto:

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

Creo que tengo dos problemas.

1) Mi idea 'breve y dulce' de insertar ~ tilde en las variables% 1% 2 entrantes (% ~ 1, etc.) parece haber afectado algunas configuraciones y alterado la forma en que CMD navega por los nombres de ruta largos.

2) Todavía estoy buscando una forma limpia y fácil de eliminar las comillas de las variables nombradas seleccionadas.

Cualquier ayuda para los más experimentados será muy apreciada. Estoy al final de mis habilidades aquí ... ¡necesito orientación, por favor!

editar 26/12/2009 13:36 PST archivo por lotes completo:

Blockquote
:: dataout.bat
:: revisión 12/25/2009 agregue ~ tilde a las variables% entrantes para eliminar las comillas "incrustadas.
:: escribe la lista de direcciones utilizando parámetros de línea de comando
:: escribe la lista de salida de datos para la importación de QBooks IIF
:: escribe Datos de pedido de comerciante para RUI
:: cadena de línea de comando de muestra para la prueba
:: listmail [nombre] [apellido] ["cadena de dirección"] ["cadena de ciudad"] [estado] [zip] [N.º de pedido] [PurchDate] [Nombre de registro] ["FirstName LastName"] [TransactionID] [PaymentMethod] [Total] [ProductID] [Qty] [Price_Each] [PackPrep] [Shipping] [CommissionPmt] [Invoice #]
:: ejemplo: salida de datos 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 y configuración \ administrador \ mis documentos \ txt \
procesamiento de eco por
lotes % 1% 2 : VARISET
::Convierta% n parámetros de línea de comando en variables de cadena
set ($ FirstName) =% ~ 1
set ($ LastName) =% ~ 2
set ($ BillingAddress1) =% ~ 3
set ($ BillingCity) =% ~ 4
set ($ BillingState) =% ~ 5
conjunto ($ BillingPostal) =% ~ 6
conjunto ($ OrderNumber) =% ~ 7
conjunto ($ Purch_Date) =% ~ 8
conjunto ($ RegistrationName) =% ~ 9

conjunto de turnos ($ TransactionID) =% ~ 9 conjunto de
turnos
($ PaymentMethod) =% ~ 9 conjunto de
turnos
($ Total) =% ~ 9
conjunto de turnos ($ ProductIdentifier) ​​=% ~ 9 conjunto de
turnos
($ Cantidad) =% ~ 9 conjunto de
turnos
($ Price_Each) =% ~ 9 conjunto de
turnos
($ Pack_Prep) =% ~ 9 conjunto de
turnos
($ Envío) =% ~ 9 conjunto de
turnos
($ ServiceFee) =% ~ 9 conjunto de
turnos
($ Descuento) =% ~ 9
shift
set ($ Invoice) =% ~ 9
shift
set ($ UnitPrice) =% ~ 9
set _ShipCombName =% ($ FirstName) %% ($ LastName )%
echo el nombre del combo de envío es% _ShipCombName%
pause
:: escribir variables de cadena en el archivo de registro
echo FN% ($ FirstName)% LN% ($ LastName)% BA% ($ BillingAddress1)%% ($ BillingCity)%% ($ BillingState)%% ($ BillingPostal)%% ($ OrderNumber)%% ($ Purch_Date)%% ($ RegistrationName)%% ($ TransactionID)%% ($ PaymentMethod)%% ($ Total)%% ($ ProductIdentifier)%% ($ Cantidad)%% ($ Price_Each) %% ($ Pack_Prep)%% ($ Envío)%% ($ ServiceFee)%% ($ Discount)%% ($ Invoice)%% ($ UnitPrice)%% _ShipCombName% >> d_out_log.txt
:: Asignar cuenta por Proveedor de servicios
IF / i% ($ PaymentMethod)% == Amazon Receivables SET _QBAcct = Amazon.com
:: 12-25-2009 agregado el segundo método de Amazon pm't para la versatilidad
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)% == En la cuenta 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
:: Asignar el designador de representante basado en QBAccount
IF / i% ($ PaymentMethod)% == Amazon Receivables SET _Rep = Amazon
:: 12-25-2009 agregado el segundo método de Amazon pm't para la versatilidad
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)% == En cuenta SET _Rep = RB
IF / i% ($ PaymentMethod)% == Mail SET _Rep = RB
IF / i% ($ PaymentMethod)% == AMER SET _Rep = BlueZap
IF / i % ($ PaymentMethod)% == DISC SET _Rep = BlueZap
:: buscar datos de direcciones duplicados
findtr / 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
Archivo de dirección de eco Escrito
: ADDRFOUND El
representante de eco seleccionado es% _Rep% El
eco de la cuenta seleccionada es:% _QBAcct%
pause
:: RUI OUT
:: escribir ID de pedido de comerciante y ID de pedido de RUI en RUI
:: comprobar datos de RUI duplicados en 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
:: Compruebe si hay datos de facturas duplicados en writeIIF.txt
find / i "% ($ OrderNumber)%" writeIIF.txt
echo errorlevel:% errorlevel%
if errorlevel 1 goto: HEADWRITE
if errorlevel 0 goto: LINEWRITE
: HEADWRITE
:: write Encabezado, Envío / Manejo, descuento, Representante y datos de comisión al QB IIF archivo de importación
echo% ($ OrderNumber)%% ($ Purch_Date)% Factura% ($ TransactionID)%% _QBAcct% Cuentas por cobrar% ($ Total)%% _Rep % >> writeIIF.txt
echo H / P% ($ Pack_Prep)% 1? >> writeIIF.txt
echo SHP% ($ Envío)% 1? >> writeIIF.txt
echo DISC% ($ Descuento)% 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
:: escribe precios con descuento analizados de la variable personalizada:
echo% ($ ProductIdentifier) %% ($ Price_Each)%% ($ Cantidad)%? >> writeIIF.txt
goto: EOF
: WRITE_DEFA
: escribe los precios predeterminados analizados de los datos del producto
echo% ($ ProductIdentifier)%% ($ UnitPrice)%% ($ Cantidad)%? >> writeIIF.txt
goto: EOF
:: retraso de 3 segundos
:: TYPE NUL | CHOICE.COM / N / CY / TY, 3> NUL
: EOF

BobB
fuente
¿Podrías usar PowerShell para hacer esto? Sospecho que obtendrá un poco más de control si usa PowerShell.
Robert Harvey
1
Revisé su archivo por lotes, parece que funciona bien (después de que arreglé la línea "shift set ($ ProductIdentifier) ​​=% ~ 9", que, creo, es un artefacto de copiarlo y pegarlo aquí).
atzz
Gracias Robert Harvey; He estado mirando PowerShell. No tengo mucha experiencia con la programación ... no estoy seguro de cómo sería la curva de aprendizaje. Tengo algo de experiencia con archivos por lotes, razón principal por la que elegí esto. Tengo la intención de compilar el lote para que se ejecute más rápido. Gracias por responder.
BobB
Gracias atzz: desde entonces he probado este archivo por lotes un poco más y estoy razonablemente seguro de que ~ tilde y las comillas de destierro no están relacionadas con el problema de CMD con nombres de ruta largos. Lo solucioné configurando un subdirectorio de nombre corto cerca de la raíz para eliminar los nombres de ruta largos.
BobB
No es necesario mostrar el archivo por lotes completo. Acorte su pregunta.
jor

Respuestas:

192

Tiene una comilla doble adicional al final, que es volver a agregarla al final de la cadena (después de eliminar ambas comillas de la cadena).

Entrada:

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

Salida:

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

Nota: Para reemplazar Comillas dobles "por Comillas simples", haga lo siguiente:

set widget=%widget:"='%

Nota: Para reemplazar la palabra "Mundo" (no distingue entre mayúsculas y minúsculas) por BobB, haga lo siguiente:

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

Salida:

widget="Hello BobB!"

En lo que respecta a su pregunta inicial (guarde el siguiente código en un archivo por lotes .cmd o .bat y ejecútelo):

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

Salida:

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

%0es el nombre y la ruta del script.
%1es el primer argumento de la línea de comandos, y así sucesivamente.

Sr. Rick
fuente
Gracias, esto era lo que buscaba SET BathFileAndPath=%~0(en realidad, mi matriz de parámetros comienza con 1, así que uséSET BathFileAndPath=%~1
Valamas
¿Puede explicar por qué %widget:"=%se deshacen de las comillas?
CodyBugstein
4
@Imray: :old=newes un patrón de coincidencia y reemplazo en la expansión de la variable. Con "como el oldy nada como el new, las comillas se eliminan, incluso si están en el medio, incluso si están desequilibradas.
Jesse Chisholm
set widget =% widget: "=% tiene un comportamiento extraño cuando el widget está en blanco, devuelve" = "
Rahul Misra
43

Su conclusión (1) suena incorrecta. Debe haber algún otro factor en juego.

El problema de las comillas en los parámetros de archivos por lotes normalmente se resuelve eliminando las comillas con %~y luego volviéndolas a colocar manualmente cuando corresponda.

P.ej:

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

"%cmd%" %params%

Tenga en cuenta las comillas alrededor %cmd%. Sin ellos, el camino con espacios no funcionará.

Si pudiera publicar su código de lote completo, tal vez podría hacerse una respuesta más específica.

atzz
fuente
1
De acuerdo; Me parece que el conjunto var =% ~ 1 debería funcionar bien. Publicaré el archivo por lotes completo según lo solicitado.
BobB
Referencia de MS: Uso de parámetros de lote . ¿Quién diría que había tantos modificadores? Como referencia, el documento oficial de MS proporciona la descripción de %~1asExpands %1 and removes any surrounding quotation marks ("").
cod3monk3y
@ cod3monk3y Además, es posible preguntarse cmdacerca de estos modificadores: call /?para obtener ayuda sobre modificadores de parámetros, set /?para modificadores de variables (probablemente no muy intuitivo). Muy útil.
atzz
12

Por lo general, elimino todas las comillas de mis variables con:

set var=%var:"=%

Y luego aplicarlos nuevamente donde los necesite, por ejemplo:

echo "%var%"
t1ck
fuente
También tuve problemas con esto al principio, resultó que lo estaba viendo :como un .- después de darme cuenta de eso, funcionó sin problemas. ¡Buen consejo!
DaveU
9

Pasé mucho tiempo tratando de hacer esto de una manera simple. Después de mirar el bucle FOR cuidadosamente, me di cuenta de que puedo hacer esto con solo una línea de código:

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

Ejemplo:

@ECHO OFF
SET Quoted="Test string"

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

ECHO %Quoted%
ECHO %Unquoted%

Salida:

"Test string"
Test string
Vitaliy Ulantikov
fuente
Este método no es relevante mientras "SET Quoted = Test string". La siguiente pregunta es cómo diferir si "(comillas dobles) existe o no. A quien pueda interesarle, gracias de
antemano
3

Esto suena como un simple error en el que está usando% ~ en algún lugar donde no debería estar. El uso de if% ~ no cambia fundamentalmente la forma en que funcionan los archivos por lotes, solo elimina las comillas de la cadena en esa única situación.

John Knoeller
fuente
3

Aprendí de este enlace , si está usando XP o superior, esto simplemente funcionará por sí solo:

SET params = %~1

No pude hacer que ninguna de las otras soluciones aquí funcionara en Windows 7.

Para iterar sobre ellos, hice esto:

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

Nota: Solo obtendrá comillas dobles si pasa argumentos separados normalmente por un espacio.


fuente
0
  1. set widget = "un elemento muy útil"
  2. establecer widget
  3. widget = "un elemento muy útil"
  4. establecer widget =% widget: "=%"
  5. establecer widget
  6. establecer widget = un elemento muy útil "

La cita final "en la línea 4 agrega una cita "a la cadena. Debería eliminarse. La sintaxis de la línea 4 termina con%

David
fuente
@ user195488 - lea la línea 3 como observe que se muestra:widget="a very useful item" y lea la línea 6 como observe que muestra:widget=a very useful item" y entienda que la línea 7 sería set widget=%widget:"=%y la línea 8 sería observar que la línea mostrada widget=a very useful itemya no tiene una comilla final .
Jesse Chisholm
0

Pensé que tenía la solución, pero pronto experimenté un comportamiento inusual con la ejecución de archivos por lotes. De repente, CMD no reconoce declaraciones de largo recorrido. Ejecución normal del archivo por lotes desde la ruta completa

C: \ Documentos y configuración \ Administrador \ Mis documentos \ Txt \ batchtest \ dataout.bat

devoluciones

'C: \ Documentos' no se reconoce como un comando interno o externo ...

Ahí está todo tu problema. CMD no entiende los espacios dentro de los nombres de archivo desde la línea de comando, por lo que cree que está intentando pasar

y Configuración \ Administrador \ Mis documentos \ Txt \ batchtest \ dataout.bat

como parámetros para el

"C: \ Documentos"

programa.

Debe citarlo para ejecutar un archivo por lotes con espacios en la ruta:

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

hubiera funcionado.

CarryWise
fuente
0
@echo off

Setlocal enabledelayedexpansion

Set 1=%1

Set 1=!1:"=!

Echo !1!

Echo "!1!"

Set 1=

Demuestra con o sin comillas, independientemente de si el parámetro original tiene comillas o no.

Y si desea probar la existencia de un parámetro que puede o no estar entre comillas, coloque esta línea antes de los ecos de arriba:

Si '% 1' == '' ve a tu

Pero si verifica la existencia de un archivo que puede o no tener comillas, entonces es:

Si EXISTE "! 1!" ir a otrosub

Tenga en cuenta que el uso de comillas simples y dobles es diferente.

Aaron Lowe
fuente
0

Todas las respuestas están completas. Pero quería agregar una cosa,

establecer FirstName =% ~ 1

establecer Apellido =% ~ 2

Esta línea debería haber funcionado, necesitabas un pequeño cambio.

establecer "Nombre =% ~ 1"

establecer "Apellido =% ~ 2"

Incluya la tarea completa entre comillas. Eliminará las comillas sin problemas. Esta es una forma preferida de asignación que corrige problemas no deseados con comillas en los argumentos.

Nombre de código Jack
fuente
0

La sintaxis de tilde simple funciona solo para eliminar las comillas alrededor de los parámetros de la línea de comando que se pasan a los archivos por lotes

SET xyz=%~1

El código del archivo por lotes anterior establecerá xyz en cualquier valor que se esté pasando como primer parámetro, eliminando las citas iniciales y finales (si están presentes).

Pero, esta sintaxis simple de tilde no funcionará para otras variables que no se pasaron como parámetros

Para todas las demás variables, debe utilizar la sintaxis de sustitución expandida que requiere que especifique los caracteres iniciales y retrasados ​​que se eliminarán. Efectivamente, estamos indicando que eliminemos el primer y el último carácter sin mirar lo que realmente es.

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

Si quisiéramos verificar cuál era el primer y último carácter en realidad antes de eliminarlo, necesitaremos un código adicional de la siguiente manera

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