web-dev-qa-db-fra.com

Comment remplacer une chaîne dans un fichier bat par un paramètre de ligne de commande

J'ai suivant dans un fichier de commandes cmd:

for /f %%l in (%2) do (for %%f in (%%l) do copy "%%f" %1))

remarque: ce script ne lit en principe qu'un fichier texte contenant un fichier txt délimité par des points-virgules dont le chemin est indiqué par% 2 (par exemple, qui contient c:\test1\fichier1.cs; d:\fichier2.js) et copie les fichiers dans la destination dossier spécifié par% 1.

Je dois remplacer la valeur de chaîne du paramètre %1 par x (qui est également transmise au fichier de traitement par lots, par exemple %3) par la valeur %4, qui est également transmise en tant que paramètre au fichier de traitement par lots.

par exemple.: 

if %1 = 'test replace x with y'
%3=x
%4=y

donc le résultat devrait être 'test remplace y par y'

Comment puis-je atteindre cet objectif à l'aide de l'interpréteur de lot Windows CMD?

12
DSharper

Tout d’abord, vous devrez stocker %1

ce qui signifie: 'remplacez chaque str1 dans variable par str2'.

Dans votre cas, str1 et str2 sont des paramètres et non des chaînes littérales. En utilisant directement le modèle ci-dessus, vous pourriez vous retrouver avec cette expression:

%variable:%3=%4%.

Mais cela dérouterait l’analyseur, car il ne saurait pas que %3 et %4 devraient être évalués en premier. En fait, il essaiera d’abord d’évaluer %variable:% (et échouera).

Une des solutions dans ce cas pourrait être d’utiliser une méthode appelée évaluation retardée 'lazy'} _. Fondamentalement, vous passez la commande où vous évaluez une variable, à la commande CALL. La transformation de la commande d'origine en sa version CALL ressemble à ceci:

ECHO %var% ==> CALL ECHO %%var%%.

Notez le double %s. Au moment de l'analyse, ils sont évalués avec un % unique. La commande résultante serait à nouveau analysée par CALL et l'effet final serait le même que dans le cas de la commande d'origine, ECHO %var%.

Donc, cela fonctionne de la même manière que la commande originale (ce qui est bon), et ce que nous gagnons ici, c’est la dernière fois de l’évaluation, _, je veux dire l’évaluation finale, lorsque la variable est remplacée par sa valeur. Connaissant cet effet, nous pouvons construire notre expression de manière à ce que %3 et %4 soient évalués en premier, puis à l'expression résultante entière. Plus précisément, comme ceci:

%%variable:%3=%4%%

Après la première analyse, cette expression deviendrait quelque chose comme ceci:

%variable:x=y%

Cela serait analysé à nouveau et le résultat serait le contenu modifié de variable.

Pour une meilleure illustration, voici un exemple de travail simple:

SET "output=%1"
CALL SET output=%%output:%3=%4%%
ECHO %output%

METTRE À JOUR

Il existe une autre méthode pour faire la même chose, que j'aurais probablement dû mentionner en premier.

La commande Windows Shell prend en charge une expansion retardée correcte. Il est plus simple à utiliser, mais comporte quelques réserves.

Tout d'abord, comment l'utiliser. La syntaxe pour une expansion retardée est !var! au lieu de %var% pour une expansion immédiate (qui reste valide et peut être utilisée avec la syntaxe d'expansion retardée).

!var! ne fonctionnera probablement pas dans votre script tant que vous n'activez pas la syntaxe à l'aide de la commande:

SETLOCAL EnableDelayedExpansion

La commande ENDLOCAL ferme le bloc dans lequel la syntaxe d'expansion retardée est valide et interprétée par la commande Shell.

L'exemple de script ci-dessus pourrait être réécrit comme ceci:

SET "output=%1"
SETLOCAL EnableDelayedExpansion
SET output=!output:%3=%4!
ECHO !output!
ENDLOCAL

Alors, comment cela fonctionne dans le cas de la commande SET output=!output:%3=%4!:

  • %3 et %4 sont évalués immédiatement, c'est-à-dire au moment de l'analyse - ils sont remplacés par x et y respectivement;

  • la commande devient ceci: SET output=!output:x=y!;

  • la commande est sur le point de s'exécuter - l'expression ! est évaluée (les xs sont remplacés par ys);

  • la commande est exécutée - la variable output est modifiée.

Passons maintenant aux mises en garde. La première chose à retenir est que le ! fait partie de la syntaxe et est consommé et interprété chaque fois qu'il est rencontré. Vous devrez donc y échapper là où vous voulez l’utiliser littéralement (comme ^!).

Un autre inconvénient est l'effet principal d'un bloc SETLOCAL/ENDLOCAL. Le fait est que tous les changements apportés aux variables d'environnement dans un tel bloc sont, bien, locaux. En quittant le bloc (en exécutant ENDLOCAL), la variable est définie sur la valeur qu'elle avait avant de la saisir (avant d'exécuter SETLOCAL). Cela signifie pour vous que la valeur modifiée de output ne sera valide que dans le bloc SETLOCAL que vous avez dû initier pour utiliser l'extension retardée en premier lieu. Cela n’est peut-être pas un problème dans votre cas particulier, si vous avez juste besoin de modifier la valeur, puis de l’utiliser tout de suite, mais vous devriez probablement vous en souvenir à l’avenir.

Remarque: Selon le commentaire de jeb, vous pouvez enregistrer la valeur modifiée et laisser le bloc SETLOCAL en utilisant cette astuce:

ENDLOCAL & SET "output=%output%"

L'opérateur & délimite simplement les commandes lorsqu'elles sont placées sur la même ligne. Ils sont exécutés les uns après les autres, dans le même ordre où ils sont spécifiés. Au moment de l’analyse de la ligne, le bloc SETLOCAL n’a pas encore été laissé, donc %output% est évalué à la valeur modifiée, qui est toujours valide. Mais l’affectation est réellement exécutée aprèsENDLOCAL, c’est-à-dire après avoir quitté le bloc. Ainsi, vous stockez effectivement la valeur modifiée après avoir quitté le bloc, préservant ainsi les modifications. (Merci, jeb!)


Plus d'information:

  1. Sur expansion retardée:

  2. Sur remplacement de sous-chaîne:

50
Andriy M

J'ai essayé ci-dessous le code dans le fichier de commandes Windows 7:

SET output=%1
CALL SET output=%output:unsigned=signed%
CALL SET output=%output:.apk=-aligned.apk%

Ça marche !

2
Eddie Cheung

Si vous devez substituer plusieurs paramètres dans une chaîne, utilisez simplement "for/f" pour définir la variable avec la substitution précédente comme ceci:

SET "output1=%1"
CALL SET output1=%%output1:%3=%4%%
for /f "tokens=1" %%a in ('echo %output1%') do set output2=%%a
CALL SET output2=%%output2:%5%6%
for /f "tokens=1" %%a in ('echo %output2') do set output3=%%a
0
michael