La suppression des guillemets doubles des variables dans le fichier de commandes crée des problèmes avec l'environnement CMD

117

Quelqu'un peut-il aider avec un moyen efficace et sûr de supprimer les citations des variables de lot?

J'ai écrit un fichier batch qui importe avec succès une liste de paramètres% 1,% 2,% 3 etc. et les place dans des variables nommées. Certains de ces paramètres contiennent plusieurs mots et sont par conséquent placés entre guillemets.

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

Ces% variables sont ensuite placées dans des variables nommées:

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

la vérification des variables se fait par écho.

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

les résultats s'affichent comme

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

Je dois éliminer les citations incluses sur les variables sélectionnées. Par exemple, FirstName et LastName sont utilisés ailleurs et ne doivent pas inclure de guillemets.

Dans un fichier batch de test, j'ai réussi à éliminer les guillemets en utilisant le caractère ~ tilde dans les variables.

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

Je pensais avoir la solution, mais j'ai rapidement connu un comportement inhabituel lors de l'exécution de fichiers batch. Soudain, CMD ne reconnaît plus les instructions de long chemin. Exécution normale du fichier de commandes à partir du chemin complet

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

Retour

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

Il semblerait donc que l'ajout du caractère ~ tilde aux variables entrantes% 1% 2 ...% n ait entraîné des changements. Peut-être que certaines variables d'environnement ont été modifiées?

J'ai également essayé d'effacer les guillemets de la variable avec diverses tentatives en utilisant la commande FOR. Cela semble gênant et je n'ai pas pu apprendre comment y parvenir en créant une liste de variables pour effectuer la tâche:

quelque chose comme ça:

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

Je pense que j'ai deux problèmes.

1) Mon idée «courte et douce» d'insérer ~ tilde dans les variables entrantes% 1% 2 (% ~ 1, etc.) semble avoir affecté certains paramètres et modifié la façon dont CMD navigue dans les chemins longs.

2) Je suis toujours à la recherche d'un moyen propre et simple d'éliminer les citations des variables nommées sélectionnées.

Toute aide pour les plus expérimentés serait très appréciée. Je suis à la fin de mes compétences ici ... besoin de conseils s'il vous plaît!

modifier 12/26/2009 13:36 PST fichier de commandes entier:

Blockquote
:: dataout.bat
:: révision 12/25/2009 ajoute ~ tilde aux variables% entrantes pour éliminer les guillemets incorporés ".
:: écrit la liste d'adresses en utilisant les paramètres de ligne de commande
:: écrit la liste de sortie des données pour QBooks IIF import
:: écrit Données de la commande du marchand pour RUI
:: exemple de chaîne de ligne de commande pour les tests
:: listmail [prénom] [nom] ["chaîne d'adresse"] ["chaîne de ville"] [état] [zip] [numéro de commande] [date de péremption] [nom d'enregistrement] ["FirstName LastName"] [TransactionID] [PaymentMethod] [Total] [ProductID] [Qty] [Price_Each] [PackPrep] [Shipping] [CommissionPmt] [Invoice #]
:: exemple: 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 documents and settings \ administrator \ my documents \ txt \ batchtest
traitement de l'écho% 1% 2
: VARISET
::Convertir les paramètres de ligne de commande% n en variables de chaîne
set ($ FirstName) =% ~ 1
set ($ LastName) =% ~ 2
set ($ BillingAddress1) =% ~ 3
set ($ BillingCity) =% ~ 4
set ($ BillingState) =% ~ 5
set ($ BillingPostal) =% ~ 6
set ($ OrderNumber) =% ~ 7
set ($ Purch_Date) =% ~ 8
set ($ RegistrationName) =% ~ 9
shift
set ($ TransactionID) =% ~ 9
shift
set ($ PaymentMethod) =% ~ 9
shift
set ($ Total) =% ~ 9
shift set ($ ProductIdentifier) ​​=% ~ 9
shift
set ($ Quantity) =% ~ 9
shift IF / i% ($ PaymentMethod)% == MasterCard SET _Rep = BlueZap IF / i% ($ PaymentMethod)% == Visa SET _Rep = BlueZap IF / i% ($ PaymentMethod)% == PayPal SET _Rep = BlueZap IF / i% ($ PaymentMethod)% == On Account SET _Rep = RB echo% ($ BillingCity)%% ($ BillingState)%% ($ BillingPostal)% >> addrlist.txt echo. >> addrlist.txt echo Fichier d'adresse écrit : ADDRFOUND écho sélectionné rep est% _Rep% echo compte sélectionné est:% _QBAcct%
ensemble de ($ Price_Each) =% ~ 9 ensemble de
décalage
($ Pack_Prep) =% ~ 9 ensemble de
décalage
($ Shipping) =% ~ 9 ensemble de
décalage
($ ServiceFee) =% ~ 9 ensemble de
décalage
($ Discount) =% ~ 9
shift
set ($ Invoice) =% ~ 9
shift
set ($ UnitPrice) =% ~ 9
set _ShipCombName =% ($ FirstName)%% ($ LastName)% le
nom de la combinaison d'écho du navire est% _ShipCombName%
pause
:: écrire des variables de chaîne dans le fichier journal
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 Fournisseur de services
IF / i% ($ PaymentMethod)% == Amazon Receivables SET _QBAcct = Amazon.com
:: 12-25-2009 a ajouté une deuxième méthode Amazon pm't pour la polyvalence
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)% == On Account 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 designator basé sur QBAccount
IF / i% ($ PaymentMethod)% == Amazon Receivables SET _Rep = Amazon
:: 12-25-2009 a ajouté une deuxième méthode Amazon pm't pour la polyvalence
IF / i% ($ PaymentMethod)% == Amazon SET _Rep = Amazon
IF / i% ($ PaymentMethod)% == MAST SET _Rep = BlueZap




IF / i% ($ PaymentMethod)% == Mail SET _Rep = RB
IF / i% ($ PaymentMethod)% == AMER SET _Rep = BlueZap
IF / i % ($ PaymentMethod)% == DISC SET _Rep = BlueZap
:: vérifier les données d'adresse en double
findstr / i / s "% _ShipCombName%" addrlist.txt
echo errorlevel:% errorlevel%
si errorlevel 1 goto: ADDRWRITE
if errorlevel 0 goto: ADDRFOUND
: ADDRWRITE
echo% _ShipCombName% >> addrlist.txt
echo% ($ BillingAddress1)% >> addrlist.txt






pause
:: RUI OUT
:: écrire l'ID de commande du marchand et l'ID de commande RUI dans RUI
:: vérifier les données RUI en double dans writeRUI.txt : IIFWRITE :: Vérifier les données de facturation en double dans writeIIF.txt find / i "% ($ OrderNumber) % "writeIIF.txt écho niveau d'erreur:% errorlevel%
cd ..
cd RegKOut
find / i "% ($ OrderNumber)%" writeRUI.txt
echo errorlevel:% errorlevel%
si errorlevel 1 goto: RUIWRITE
if errorlevel 0 goto: IIFWRITE
: RUIWRITE
echo% ($ Invoice)% % ($ OrderNumber)% >> writeRUI.txt
:: end write RUI
:: IIF OUT




si errorlevel 1 goto: HEADWRITE
if errorlevel 0 goto: LINEWRITE
: HEADWRITE
:: write Données d'en-tête, d'expédition / de manutention, de remise, de représentant et de commission vers le fichier d'importation 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% ($ Expédition)% 1? >> writeIIF.txt
echo DISC% ($ Discount)% 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
:: écrit des prix réduits analysés à partir de la variable personnalisée:
echo% ($ ProductIdentifier) %% ($ Price_Each)%% ($ Quantity)%? >> writeIIF.txt
goto: EOF :: Retard de 3 secondes :: TYPE NUL | CHOICE.COM / N / CY / TY, 3> NUL : EOF
: WRITE_DEFA
: écrit les prix par défaut analysés à partir des données produit
echo% ($ ProductIdentifier)%% ($ UnitPrice)%% ($ Quantity)%? >> writeIIF.txt
goto: EOF


BobB
la source
Pourriez-vous utiliser PowerShell pour ce faire? Je suppose que vous obtiendrez un peu plus de contrôle si vous utilisez PowerShell.
Robert Harvey
1
J'ai vérifié votre fichier de commandes - cela semble fonctionner correctement (après avoir corrigé la ligne "shift set ($ ProductIdentifier) ​​=% ~ 9" - qui, je pense, est un artefact de copier-coller ici).
atzz
Merci Robert Harvey; J'ai regardé PowerShell. Je ne suis pas très expérimenté avec la programmation ... je ne sais pas à quoi ressemblerait la courbe d'apprentissage. J'ai une certaine expérience avec les fichiers batch, raison principale pour laquelle j'ai choisi cela. J'ai l'intention de compiler le lot pour qu'il s'exécute plus rapidement. Merci pour la réponse.
BobB
Merci atzz: J'ai depuis testé ce fichier batch un peu plus et je suis raisonnablement convaincu que le ~ tilde et les citations de bannissement ne sont pas liés au problème CMD w / longs chemins. J'ai contourné cela en configurant simplement un sous-répertoire de nom court près de la racine pour éliminer les longs chemins.
BobB
Pas besoin d'afficher le fichier de commandes complet. Veuillez raccourcir votre question.
jor

Réponses:

193

Vous avez un guillemet double supplémentaire à la fin, qui l'ajoute à la fin de la chaîne (après avoir supprimé les deux guillemets de la chaîne).

Contribution:

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

Production:

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

Remarque: pour remplacer Double Quotes "par Single Quotes ', procédez comme suit:

set widget=%widget:"='%

Remarque: pour remplacer le mot «Monde» (non sensible à la casse) par BobB, procédez comme suit:

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

Production:

widget="Hello BobB!"

En ce qui concerne votre question initiale (enregistrez le code suivant dans un fichier de commandes .cmd ou .bat et exécutez):

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

Production:

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

%0est le nom et le chemin du script.
%1est le premier argument de ligne de commande, et ainsi de suite.

M. Rick
la source
Merci, c'était ce que je cherchais SET BathFileAndPath=%~0(en fait, mon tableau de paramètres commence par 1, alors j'ai utiliséSET BathFileAndPath=%~1
Valamas
Pouvez-vous expliquer pourquoi %widget:"=%se débarrasse des guillemets?
CodyBugstein
4
@Imray - :old=newest une correspondance et un remplacement de modèle dans le développement de variables. Avec "comme le oldet rien comme le new, les guillemets sont supprimés, même s'ils sont au milieu, même s'ils sont déséquilibrés.
Jesse Chisholm
set widget =% widget: "=% a un comportement étrange lorsque le widget est vide, il renvoie" = "
Rahul Misra
43

Votre conclusion (1) semble erronée. Il doit y avoir un autre facteur en jeu.

Le problème des guillemets dans les paramètres du fichier de commandes est normalement résolu en supprimant les guillemets avec %~, puis en les remettant manuellement le cas échéant.

Par exemple:

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

"%cmd%" %params%

Notez les citations autour %cmd% . Sans eux, le chemin avec des espaces ne fonctionnera pas.

Si vous pouviez publier l'intégralité de votre code de lot, une réponse plus précise pourrait peut-être être apportée.

atzz
la source
1
Je suis d'accord; il me semble que l'ensemble var =% ~ 1 devrait fonctionner correctement. Je publierai tout le fichier de commandes comme demandé.
BobB
Référence MS: Utilisation des paramètres de lot . Qui savait qu'il y avait tant de modificateurs? Pour référence, le document officiel MS donne la description de %~1asExpands %1 and removes any surrounding quotation marks ("").
cod3monk3y
@ cod3monk3y De plus, il est possible de s'interroger cmdsur ces modificateurs: call /?pour l'aide sur les modificateurs de paramètres, set /?pour les modificateurs de variables (probablement pas très intuitifs). Très pratique.
atzz le
12

En général, je supprime simplement toutes les citations de mes variables avec:

set var=%var:"=%

Et puis appliquez-les à nouveau partout où j'en ai besoin, par exemple:

echo "%var%"
t1ck
la source
J'ai également eu des problèmes avec cela au début, il s'est avéré que je voyais le :comme un .- après avoir compris cela, j'ai travaillé sans accroc. Bon conseil!
DaveU
9

J'ai passé beaucoup de temps à essayer de faire cela de manière simple. Après avoir examiné attentivement la boucle FOR, j'ai réalisé que je pouvais le faire avec une seule ligne de code:

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

Exemple:

@ECHO OFF
SET Quoted="Test string"

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

ECHO %Quoted%
ECHO %Unquoted%

Production:

"Test string"
Test string
Vitaliy Ulantikov
la source
Cette méthode n'est pas pertinente lorsque "SET Quoted = Test string". La question suivante est de savoir comment différer "(guillemets doubles) existe ou non. À qui pourrait être concerné, merci d'avance.
Rhak Kahr
3

Cela ressemble à un simple bogue où vous utilisez% ~ quelque part où vous ne devriez pas être. L'utilisation si% ~ ne change pas fondamentalement le fonctionnement des fichiers batch, elle supprime simplement les guillemets de la chaîne dans cette seule situation.

John Knoeller
la source
3

J'ai appris de ce lien , si vous utilisez XP ou une version supérieure, que cela fonctionnera simplement par lui-même:

SET params = %~1

Je ne pouvais pas faire fonctionner l'une des autres solutions ici sous Windows 7.

Pour les parcourir, j'ai fait ceci:

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

Remarque: Vous n'obtiendrez des guillemets doubles que si vous passez des arguments séparés par un espace généralement.


la source
0
  1. set widget = "un élément très utile"
  2. définir un widget
  3. widget = "un élément très utile"
  4. set widget =% widget: "=%"
  5. définir un widget
  6. set widget = un élément très utile "

Le guillemet de fin "de la ligne 4 ajoute un guillemet "à la chaîne. Il devrait être supprimé. La syntaxe de la ligne 4 se termine par%

David
la source
@ user195488 - lisez la ligne 3 comme observez qu'elle a affiché:widget="a very useful item" et lisez la ligne 6 comme observez qu'elle s'affiche:widget=a very useful item" et comprenez que la ligne 7 serait set widget=%widget:"=%et la ligne 8 observerait que la ligne affichée widget=a very useful itemn'a plus de guillemet de fin .
Jesse Chisholm
0

Je pensais avoir la solution, mais j'ai rapidement connu un comportement inhabituel lors de l'exécution de fichiers batch. Soudain, CMD ne reconnaît plus les instructions de long chemin. Exécution normale du fichier de commandes à partir du chemin complet

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

Retour

'C: \ Documents' n'est pas reconnu comme une commande interne ou externe ....

Voilà votre problème. CMD ne comprend pas les espaces à l'intérieur des noms de fichiers à partir de la ligne de commande, il pense donc que vous essayez de passer

et Settings \ Administrator \ My Documents \ Txt \ batchtest \ dataout.bat

en tant que paramètres du

"C: \ Documents"

programme.

Vous devez le citer pour exécuter un fichier de commandes avec des espaces dans le chemin:

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

aurait fonctionné.

CarryWise
la source
0
@echo off

Setlocal enabledelayedexpansion

Set 1=%1

Set 1=!1:"=!

Echo !1!

Echo "!1!"

Set 1=

Démontre avec ou sans guillemets, indépendamment du fait que le paramètre d'origine a des guillemets ou non.

Et si vous souhaitez tester l'existence d'un paramètre qui peut être ou non entre guillemets, mettez cette ligne avant les échos ci-dessus:

Si '% 1' == '' va à votre sous

Mais si vous vérifiez l'existence d'un fichier qui peut ou non avoir des guillemets, c'est:

Si EXISTENT "! 1!" aller à d'autres

Notez que l'utilisation des guillemets simples et des guillemets doubles est différente.

Aaron Lowe
la source
0

Toutes les réponses sont complètes. Mais je voulais ajouter une chose,

définir FirstName =% ~ 1

définir LastName =% ~ 2

Cette ligne aurait dû fonctionner, vous aviez besoin d'un petit changement.

définir "FirstName =% ~ 1"

définir "LastName =% ~ 2"

Incluez le devoir complet entre guillemets. Cela supprimera les citations sans problème. C'est une méthode d'affectation préférée qui résout les problèmes indésirables avec des guillemets dans les arguments.

Nom de code Jack
la source
0

La syntaxe tilde simple fonctionne uniquement pour supprimer les guillemets autour des paramètres de ligne de commande passés dans les fichiers de commandes

SET xyz=%~1

Le code du fichier de commandes ci-dessus définira xyz sur la valeur qui est passée en tant que premier paramètre en supprimant les guillemets de début et de fin (si présents).

Mais, cette simple syntaxe de tilde ne fonctionnera pas pour les autres variables qui n'ont pas été transmises en tant que paramètres

Pour toutes les autres variables, vous devez utiliser une syntaxe de substitution étendue qui vous oblige à spécifier les caractères de début et de retard à supprimer. En fait, nous demandons de supprimer le premier et le dernier caractère sans regarder ce qu'il est réellement.

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

Si nous voulions vérifier ce que le premier et le dernier caractère étaient réellement une citation avant de le supprimer, nous aurons besoin d'un code supplémentaire comme suit

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