windows - Sådan erstattes streng i en flagermusfil med kommandolinjeparametersnor

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har følgende i en cmd batch fil:


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


Bemærk: dette script er i princippet læst en tekstfil, der indeholder semikolon afgrænset txt fil, hvis sti er givet af\% 2 (f.eks. som indeholder c: \ test1 \ file1.cs; d: \ file2.js) og kopier filerne til destination mappe specificeret af\% 1.


Jeg er nødt til at erstatte parametrene for \%1 parameterens strengværdi på x (som også sendes til batchfilen fx \%3) med værdien \%4, som også overføres som parameter til batch-fil.


f.eks.:


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


så udgangen skal være 'test erstatning y med y'


Hvordan kan jeg opnå dette ved hjælp af Windows CMD batch tolk?

Bedste reference


Først og fremmest skal du gemme \%1 til en variabel, så vil du kunne udføre udskiftningerne.


I grund og grund er syntaksen til udskiftningen dette:


\%variable:str1=str2\%


hvilket betyder: 'erstat alle str1 i variable med str2' .


I dit tilfælde er både str1 og str2 parametre, ikke bogstavelige strenge. Ved hjælp af ovenstående skabelon kan du ende med dette udtryk:


\%variable:\%3=\%4\%.


Men det ville forvirre parseren, som det ikke ville vide, at \%3 og \%4 skulle evalueres først. Faktisk ville det først forsøge at evaluere \%variable:\% (og fejle).


En af løsningerne i denne sag kan være at bruge en metode kaldet 'doven' forsinket evaluering . Dybest set overfører du kommandoen, hvor du vurderer en variabel til CALL-kommandoen. Omdannelsen af ​​den oprindelige kommando til sin 'CALL version' er som sådan:


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


Bemærk de dobbelte \% s. Ved parse tid evalueres de til single \% s. Den resulterende kommando vil blive analyseret igen af ​​CALL, og den ultimative effekt ville være den samme som i tilfælde af den oprindelige kommando, ECHO \%var\%.


Så det virker som det originale kommando (hvilket er godt), og hvad vi får her er den senere evalueringstid , jeg mener den endelige evaluering, når variablen faktisk erstattes med dens værdi . At vide om den effekt kan vi konstruere vores udtryk på en sådan måde, at \%3 og \%4 evalueres først og derefter hele det resulterende udtryk. Nærmere bestemt, sådan:


\%\%variable:\%3=\%4\%\%


Efter den første parse ville dette udtryk blive sådan som sådan:


\%variable:x=y\%


Det ville blive analyseret igen, og output ville være variable s ændrede indhold.


For bedre illustration er her et simpelt arbejdseksempel:


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





UPDATE


Der er en anden metode til at gøre det samme, som jeg nok skulle have nævnt først.


Windows-kommandopålet understøtter en korrekt forsinket ekspansion. Det er enklere i brug, men har nogle advarsler.


Først, hvordan man bruger det. Syntaxen for forsinket ekspansion er !var! i stedet for \%var\% for øjeblikkelig ekspansion (som fortsat er gyldig og kan bruges sammen med den forsinkede ekspansionssyntax).


Sandsynligvis !var! fungerer ikke i dit script, før du aktiverer syntaksen med kommandoen:


SETLOCAL EnableDelayedExpansion


Kommandoen ENDLOCAL lukker blokken, inden for hvilken den forsinkede ekspansionssyntax er gyldig og fortolket af kommandoskallen.


Ovenstående eksempel script kunne omskrives som dette:


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


Så hvordan fungerer det i tilfælde af kommandoen SET output=!output:\%3=\%4!:



  • \%3 og \%4 evalueres straks, dvs. i parsetiden - de erstattes med henholdsvis x og y;

  • Kommandoen bliver denne: SET output=!output:x=y!;

  • kommandoen er ved at udføre - ! udtryk er evalueret (x s erstattes med y s);

  • kommandoen udføres - variablen output er ændret.



Nu om advarslerne. Den første ting at huske er, at ! bliver en del af syntaksen og bliver fortæret og fortolket, når den opstår. Så du skal undslippe det, hvor du vil bruge det som en bogstavelig (som ^!).


En anden advarsel er den primære effekt af en SETLOCAL/ENDLOCAL blok. Sagen er, alle ændringer i miljøvariabler inden for en sådan blok er, godt, lokalt. Ved udgangen af ​​blokken (ved udførelse af ENDLOCAL) indstilles variablen til den værdi, den havde forud for indtastning af den (forud for udførelse af SETLOCAL). Det betyder for dig, at den ændrede værdi af output kun vil være gyldig inden for SETLOCAL -blokken, som du skulle starte for at bruge den forsinkede udvidelse i første omgang. Det kan muligvis ikke være et problem i dit særlige tilfælde, hvis du bare skal ændre værdien og derefter bruge den med det samme, men du skal nok huske det for fremtiden.


Bemærk: I henhold til jeb s kommentar kan du gemme den ændrede værdi og forlade SETLOCAL-blokken ved hjælp af dette trick:


ENDLOCAL & SET "output=\%output\%"


Operatøren & afgrænser simpelthen kommandoerne, når de placeres på samme linje. De udføres efter hinanden i samme rækkefølge, de er angivet. Sagen er, ved øjeblikket at analysere linjen, er SETLOCAL-blokken ikke blevet forladt endnu, så \%output\% evaluerer til den ændrede værdi, som stadig er gyldig. Men opgaven udføres faktisk efter ENDLOCAL, dvs. efter at have forladt blokken. Så du gemmer effektivt den ændrede værdi efter at have forladt blokken, og dermed bevarer ændringerne. (Tak, jeb !)





Mere information:



  1. Ved forsinket ekspansion:



    • http://blogs.msdn.com/b/oldnewthing/archive/2006/08/23/714650.aspx [57]

    • http://www.dostips.com/DtTutoFramework.php#\_Toc128587174 [58]


  2. Ved udskiftning af substreng:



    • http://www.dostips.com/DtTipsStringOperations.php#Snippets.Replace



Andre referencer 1


Jeg har prøvet nedenstående kode i Windows 7 batch-fil: [59]


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


Det virker !

Andre referencer 2


Hvis du skal erstatte flere parametre i en streng, skal du blot bruge 'for/f' til at indstille variabel med tidligere substitution som denne:


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