it-swarm.com.de

So ersetzen Sie eine Zeichenfolge in einer bat-Datei durch die Befehlszeilenparameterzeichenfolge

Ich habe folgendes in einer Cmd-Batch-Datei:

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

hinweis: Dieses Skript liest im Wesentlichen eine Textdatei, die durch Semikolons getrennte Textdatei enthält, deren Pfad von% 2 angegeben wird (z. B. c:\test1\file1.cs; d:\file2.js) und kopiert die Dateien an das Ziel Ordner von% 1 angegeben.

Ich muss den Zeichenfolgenwert von %1 von x (der auch an die Batchdatei, z. B. %3, übergeben wird) durch den %4-Wert ersetzen, der ebenfalls als Parameter an die Batchdatei übergeben wird.

z.B.: 

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

die Ausgabe sollte also "test ersetzen y durch y" sein.

Wie kann ich dies mit dem Windows CMD-Batch-Interpreter erreichen?

12
DSharper

Zuerst müssen Sie %1 in einer Variablen speichern, dann können Sie die Ersetzungen durchführen.

Grundsätzlich lautet die Syntax für die Ersetzung wie folgt:

%variable:str1=str2%

was bedeutet: 'ersetze jeden str1 in variable durch str2' .

In Ihrem Fall sind sowohl str1 als auch str2 Parameter und keine Literalzeichenfolgen. Wenn Sie die obige Vorlage direkt verwenden, erhalten Sie möglicherweise den folgenden Ausdruck:

%variable:%3=%4%.

Aber das würde den Parser verwirren, da er nicht wissen würde, dass %3 und %4 zuerst ausgewertet werden sollten. Tatsächlich würde es zuerst versuchen, %variable:% auszuwerten (und fehlschlagen).

Eine der Lösungen in diesem Fall könnte darin bestehen, eine Methode zu verwenden, die als "verzögerte" Auswertung bezeichnet wird. Grundsätzlich übergeben Sie den Befehl, in dem Sie eine Variable auswerten, an den Befehl CALL. Die Umwandlung des ursprünglichen Befehls in seine 'CALL-Version' sieht folgendermaßen aus:

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

Beachten Sie die doppelten %s. Zum Zeitpunkt der Analyse werden sie zu einzelnen %s ausgewertet. Der resultierende Befehl würde erneut von CALL analysiert und der endgültige Effekt wäre der gleiche wie im Fall des ursprünglichen Befehls ECHO %var%.

Es funktioniert also genauso wie der ursprüngliche Befehl (was gut ist), und was wir hier gewinnen, ist der spätere Zeitpunkt der Auswertung , ich meine die endgültige Auswertung, wenn die Variable ist tatsächlich durch seinen Wert ersetzt. Wenn wir diesen Effekt kennen, können wir unseren Ausdruck so konstruieren, dass zuerst %3 und %4 und dann der gesamte resultierende Ausdruck ausgewertet werden. Im Einzelnen wie folgt:

%%variable:%3=%4%%

Nach dem ersten Parsen würde dieser Ausdruck ungefähr so ​​aussehen:

%variable:x=y%

Das würde erneut analysiert und die Ausgabe würde den modifizierten Inhalt von variable enthalten.

Zur besseren Veranschaulichung hier ein einfaches Arbeitsbeispiel:

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

UPDATE

Es gibt eine andere Methode, um dasselbe zu tun, die ich wahrscheinlich zuerst hätte erwähnen sollen.

Die Windows-Befehls-Shell unterstützt eine korrekte verzögerte Erweiterung. Es ist einfacher zu bedienen, weist jedoch einige Einschränkungen auf.

Erstens, wie man es benutzt. Die Syntax für die verzögerte Erweiterung lautet !var! anstelle von %var% für die sofortige Erweiterung (die weiterhin gültig ist und zusammen mit der Syntax für die verzögerte Erweiterung verwendet werden kann).

Möglicherweise funktioniert !var! in Ihrem Skript nicht, bis Sie die Syntax mit dem folgenden Befehl aktivieren:

SETLOCAL EnableDelayedExpansion

Der Befehl ENDLOCAL schließt den Block, in dem die Syntax der verzögerten Erweiterung gültig ist, und wird vom Befehl Shell interpretiert.

Das obige Beispielskript könnte folgendermaßen umgeschrieben werden:

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

So funktioniert das im Fall des Befehls SET output=!output:%3=%4!:

  • %3 und %4 werden sofort ausgewertet, d. H. Zum Analysezeitpunkt - sie werden durch x bzw. y ersetzt;

  • der Befehl lautet wie folgt: SET output=!output:x=y!;

  • der Befehl wird ausgeführt - der Ausdruck ! wird ausgewertet (xs werden durch ys ersetzt);

  • der Befehl wird ausgeführt - die Variable output wird geändert.

Nun zu den Vorbehalten. Das Erste, woran Sie sich erinnern sollten, ist, dass ! Teil der Syntax wird und bei jedem Auftreten konsumiert und interpretiert wird. Sie müssen es also an der Stelle maskieren, an der Sie es als Literal verwenden möchten (wie ^!).

Eine weitere Einschränkung ist der primäre Effekt eines SETLOCAL/ENDLOCAL-Blocks. Die Sache ist, dass alle Änderungen an Umgebungsvariablen in einem solchen Block lokal sind. Beim Verlassen des Blocks (beim Ausführen von ENDLOCAL) wird die Variable auf den Wert gesetzt, den sie vor dem Eingeben hatte (vor dem Ausführen von SETLOCAL). Dies bedeutet für Sie, dass der geänderte Wert von output nur innerhalb des Blocks SETLOCAL gültig ist, den Sie ursprünglich für die Verwendung der verzögerten Erweiterung initiieren mussten. Möglicherweise ist dies in Ihrem speziellen Fall kein Problem, wenn Sie den Wert nur ändern und dann sofort verwenden müssen, aber Sie sollten ihn wahrscheinlich für die Zukunft merken müssen.

Hinweis: Gemäß dem Kommentar von jeb können Sie den geänderten Wert speichern und den SETLOCAL-Block mit folgendem Trick verlassen:

ENDLOCAL & SET "output=%output%"

Der Operator & grenzt die Befehle einfach ab, wenn sie in derselben Zeile stehen. Sie werden nacheinander in der angegebenen Reihenfolge ausgeführt. Das Problem ist, dass der SETLOCAL-Block zum Zeitpunkt des Parsens der Zeile noch nicht verlassen wurde, sodass %output% den geänderten Wert ergibt, der noch gültig ist. Die Zuweisung wird jedoch tatsächlich nach ENDLOCAL ausgeführt, d. H. Nach dem Verlassen des Blocks. Sie speichern also den geänderten Wert nach dem Verlassen des Blocks effektiv und behalten so die Änderungen bei. (Danke, jeb !)


Mehr Informationen:

  1. Bei verzögerter Erweiterung:

  2. Beim Ersetzen der Teilzeichenfolge:

50
Andriy M

Ich habe folgenden Code in Windows 7-Batchdatei ausprobiert:

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

Es klappt !

2
Eddie Cheung

Wenn Sie mehrere Parameter in einer Zeichenfolge ersetzen müssen, verwenden Sie einfach "for/f", um die Variable mit der vorherigen Ersetzung wie folgt festzulegen:

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