Invite de commande Windows: Utilisation d’un jeu de variables sur la même ligne que le one-liner

Bon, j’ai appris que l’on peut utiliser & ou && pour combiner plusieurs commandes dans une seule ligne, mais il semble que les variables set ne soient pas réellement disponibles pour une interpolation sur la même ligne:

 C:\Users\Andrew>set foo=hello, world!&& echo %foo% %foo% C:\Users\Andrew>echo %foo% hello, world! 

Pourquoi ne puis-je pas faire ce travail, et y a-t-il un moyen de le faire fonctionner sur une seule ligne?

La raison pour laquelle j’ai besoin d’un seul interlocuteur est qu’un programme externe avec lequel je travaille accepte une seule commande en tant que hook de pré-exécution et, bien sûr, je dois exécuter plusieurs commandes.


Défenses préventives

  1. hello, world! devrait être entouré de guillemets!” En fait, cela semble stocker des guillemets littéraux dans la variable, ce que je ne veux pas, par exemple

     C:\Users\Andrew>set bar="hello, world!"&& echo %bar% %bar% C:\Users\Andrew>echo %bar% "hello, world!" 
  2. “Il devrait y avoir un espace avant le && !” En fait, cela semble stocker un espace de fin dans la variable, ce que je ne veux pas, par exemple

     C:\Users\Andrew>set bar="hello, world!"&& echo %bar% %bar% C:\Users\Andrew>echo %bar% "hello, world!" 
  3. “Tous les deux!” > 🙁

     C:\Users\Andrew>set mu="hello, world!" && echo %mu% %mu% C:\Users\Andrew>echo (%mu%) ("hello, world!" ) 

    Vous pouvez le faire dans la même ligne, mais je vous recommande d’utiliser un fichier de commandes comme preHook.bat .

    Comme un paquebot

     set "mu=hello, world!" && call echo %^mu% 

    Au début, vous pouvez voir que les citations sont différentes des vôtres.


    Voici pourquoi:

     set test1="quotes" set "test2=no quotes" with comment 

    Dans le premier test, les guillemets feront partie de la variable test1 , ainsi que tous les caractères après la dernière citation.

    Dans le deuxième test, il utilise la syntaxe étendue de la commande SET .
    Ainsi, le contenu ne comportera no quotes , car seul le contenu de la dernière citation est utilisé; le rest sera abandonné.

    Pour faire écho au contenu de la variable, j’utilise call echo %^mu% , car le pourcentage d’extension l’étendra lorsque la ligne sera analysée, avant que l’une des commandes ne soit exécutée.

    Mais la commande call sera exécutée ultérieurement et redémarrera l’parsingur, qui, lorsqu’il est utilisé sur la ligne de commande, utilise des règles d’expansion différentes de celles de l’parsingur par lot: une variable vide (dans ce cas, %^mu% , la première fois) ) rest inchangé dans la ligne; mais, dans la prochaine phase d’parsing, le ^ caret sera supprimé.

    Dans votre cas, l’ call echo %mu% fonctionnerait également, mais seulement lorsque mu est toujours vide. La variante caret fonctionne également lorsque mu a du contenu avant l’exécution de la ligne.

    Plus d’informations sur l’parsingur de SO: Comment l’interpréteur de commandes Windows (CMD.EXE) parsing-t-il les scripts? Et à propos de l’expansion des variables à SO: expansion des variables

    Bien que j’aie accepté la réponse de @ jeb, au bout du compte, j’ai dû emprunter une autre voie, car je devais redirect la sortie de ma commande, ce qui a entraîné des résultats mutilés. En effet, la documentation pour l’ call lui call même remarque,

    N’utilisez pas de tuyaux ni de symboles de redirection avec un appel .

    Au lieu de cela, @Blorgbeard a rappelé l’option /v de cmd (et je crois que cela devrait être en minuscule, pas en majuscule), je me suis rendu compte que je pouvais simplement lancer un sous-processus:

     C:\Users\Andrew>cmd /v /c "set foo=hello, world!&& echo !foo!" hello, world! 

    (Pour une raison quelconque, /v doit apparaître avant /c .) Dans les guillemets, j’ai pu transférer ma sortie vers d’autres utilitaires. Une astuce pour ceux qui prennent ce chemin: Si vous avez besoin d’utiliser des guillemets dans ces guillemets, je suggère de les éviter complètement et d’essayer les codes de caractères, par exemple \x20 pour l’espace, \x22 pour les guillemets, etc.

    Par exemple, c’était la solution finale à mon problème ( avertissement: peut faire saigner les yeux ):

     C:\Users\Andrew>cmd /v /c "set source=C:\source& set target=C:\target& set archive=C:\archive& robocopy.exe !source! !target! /l /e /zb /xx /xl /fp /ns /nc /ndl /np /njh /njs | sed -es/^^[\t\x20]\+// | sed -e /^^$/d | sed -es/^!source:\=\\!// | sed -es/.*/xcopy\x20\/Fvikrhyz\x20\x22!source:\=\\!^&\x22\x20\x22!archive:\=\\!^&\x22/" 

    Essayez ce qui suit:

     cmd.exe /v /c "set foo=hello, world & echo !foo!" 

    L’argument /v permet l’ expansion différée des variables . Cela vous permet d’accéder aux valeurs des variables au moment de l’ exécution plutôt qu’au moment de l’ parsing (par défaut). Vous faites cela en écrivant !foo! au lieu de %foo% (avec cette option /v activée).

    Au lieu de transmettre /v , vous pouvez également activer en permanence l’extension de variable retardée via le registre, ce qui affecte évidemment tout le système:

     [HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor] "DelayedExpansion"= (REG_DWORD) 1=enabled 0=disabled (default) 

    Je ne pouvais pas faire fonctionner une commande IF avec call ou cmd / v / c . Je voudrais donc offrir une autre option à ceux qui en ont besoin: utiliser FOR / F pour déclarer et utiliser une variable dans une seule commande. Par exemple:

     FOR /F %i IN ('echo 123') DO (IF %i==123 echo done) 

    Le% i est la variable qui est définie avec le résultat de la commande IN, qui dans cet exemple est «echo 123».

    Pour les valeurs contenant des guillemets simples ou des espaces, utilisez l’indicateur “usebackq tokens = *” pour placer la commande dans les backquotes:

     FOR /F "usebackq tokens=*" %i IN (`echo "hello, ' ' world!"`) DO (IF %i=="hello, ' ' world!" echo done)