2017-03-22 3 views
0

wirkenden Parameter an ein Unterprogramm übergeben Wenn ichWie auf eine externe Datei im Batch-

setlocal EnableDelayedExpansion 
for /L %%a in (1,1,%NUMBER%) do (
    ECHO #define BLE_UUID_!SERVICE_NAME_UC!_!CARACTERISTIC_NAME_UC[%%a]!_CHAR !CARACTERISTIC_UUID[%%a]! 
) 

Wo NUMBER, SERVICE_NAME_UC, CARACTERISTIC_NAME_UC [%% a] und CARACTERISTIC_UUID [%% schreiben a] haben, bevor gesetzt worden ist, funktioniert alles einwandfrei und ich erhalten:

#define BLE_UUID_SECURITY_RELAY_CMD_CHAR  0x4800 
#define BLE_UUID_SECURITY_RELAY_STATUS_CHAR  0x4801 
#define BLE_UUID_SECURITY_CONFIG_CHAR 0x4802 

Aber was würde ich zu tun ist ein Unterprogramm innerhalb der FOR-Schleife zu nennen, die die Aufgabe hat, wie auf diese Weise:

setlocal EnableDelayedExpansion 
for /L %%a in (1,1,%NUMBER%) do (
    CALL :SetOutput_h %INPUT_HEADER_PATH%\DefCharUUID.txt %%a 
) 

GOTO:EOF 
:SetOutput_h 
:: Subroutine to insert parts of code in the header output file 
:: The argument for this subroutine is the NAME of the code part you want to insert in the output file 
SET "PART_NAME_H=%~1" 
SET "INDEX=%~2" 
(FOR /F "delims=" %%A IN ('findstr /N "^" %PART_NAME_H%') DO (

    REM Get the line *including* !variable! replacements 
    SET "line=%%A" 

    REM Remove leading number, show the rest *including* empty lines 
    ECHO(!line:*:=! 

)) >> %OUTPUT_H% 
GOTO:EOF 

Wo die Datei DefCharUUID.txt diese gerade enthält:

#define BLE_UUID_!SERVICE_NAME_UC!_!CARACTERISTIC_NAME_UC[%INDEX%]!_CHAR !CARACTERISTIC_UUID[%INDEX%]! 

Die Ausgabedatei genariert enthält:

#define BLE_UUID_SECURITY__CHAR 

So wurden Teile mit eckigen Klammern ignoriert.

Was mache ich falsch?

+0

Warum rufen Sie 'CALL' 'SetOutput_h' mit zwei Argumenten auf, von denen das erste für diese for-Schleife völlig überflüssig ist? Wenn Sie einfach PART_NAME_H =% INPUT_HEADER_PATH% \ DefCharUUID.txt "' vor dieser Schleife setzen, würden Sie nur 'CALL: SetOutput_h %% a' und' SET "INDEX =% 1" 'Ich bemerke aber auch, dass Sie es nicht tun scheinen auch% INDEX% zu benutzen! – Compo

Antwort

0

Das Problem mit Ihrem Code ist die Zeile:

SET "line=%%A" 

Die Schleifenvariable A den String-Wert hat:

#define BLE_UUID_!SERVICE_NAME_UC!_!CARACTERISTIC_NAME_UC[%INDEX%]!_CHAR !CARACTERISTIC_UUID[%INDEX%]! 

verzögerte Expansion auf die Zuweisung diese Zeichenfolge Umgebungsvariable line angewendet wird.

Aber sofortige Erweiterung für %INDEX% ist nicht mehr getan. Windows-Befehlsinterpreter erweitert, um alle Variablenreferenzen Umgebung mit %VariableName% bereits auf ganzen FüR Befehlsblock Anfang in Ihrem Code mit (FOR /F Parsen und endend mit )) bevor Befehl FOR ist das erste Mal überhaupt ausgeführt wird.

Aus diesem Grund wird !SERVICE_NAME_UC! durch die Zeichenfolge SECURITY beim Zuweisen der aus der Datei gelesenen Zeile in die Umgebungsvariable line ersetzt. Der Windows-Befehlsinterpreter kann jedoch keine Umgebungsvariable mit dem Namen CARACTERISTIC_NAME_UC[%INDEX%] und einer anderen Umgebungsvariablen mit dem Namen CARACTERISTIC_UUID[%INDEX%] finden. Dies führt dazu, dass sowohl die Pseudo-Array-Referenzen der Umgebungsvariablen durch eine leere Zeichenfolge ersetzt werden.

Ich bin mir nicht sicher, warum Sie die Erstellung der Header-Datei so kompliziert, aber hier ist die Lösung für Ihr Problem, die zusätzliche Zeilen für eine minimal, complete, and verifiable example enthält hinterlässt keine Datei hinter Batch-Dateiausführung abgeschlossen.

@echo off 
setlocal EnableExtensions 
set "NUMBER=3" 
set "SERVICE_NAME_UC=SECURITY" 
set "CHARACTERISTIC_NAME_UC[1]=RELAY_CMD" 
set "CHARACTERISTIC_NAME_UC[2]=RELAY_STATUS" 
set "CHARACTERISTIC_NAME_UC[3]=CONFIG" 
set "CHARACTERISTIC_UUID[1]=0x4800" 
set "CHARACTERISTIC_UUID[2]=0x4801" 
set "CHARACTERISTIC_UUID[3]=0x4802" 
set "INPUT_HEADER_PATH=%TEMP%" 
set "OUTPUT_H=%TEMP%\output.h" 
del "%OUTPUT_H%" 2>nul 
echo #define BLE_UUID_!SERVICE_NAME_UC!_!CHARACTERISTIC_NAME_UC[%%INDEX%%]!_CHAR !CHARACTERISTIC_UUID[%%INDEX%%]!>"%INPUT_HEADER_PATH%\DefCharUUID.txt" 

for /L %%I in (1,1,%NUMBER%) do (
    call :SetOutput_h "%INPUT_HEADER_PATH%\DefCharUUID.txt" %%I 
) 

type "%OUTPUT_H%" 
del "%OUTPUT_H%" 
del "%INPUT_HEADER_PATH%\DefCharUUID.txt" 
endlocal 
goto :EOF 

:SetOutput_h 
:: Subroutine to insert parts of code in the header output file. 
:: The argument for this subroutine is the NAME of the code part you want to insert in the output file. 
set "INDEX=%~2" 
for /F "delims=" %%L in ('%SystemRoot%\System32\findstr.exe /N "^" "%~1"') do call :ExpandLine "%%L" 
goto :EOF 

:ExpandLine 
set "Line=%~1" 
call set "Line=%Line%" 
setlocal EnableDelayedExpansion 
set "Line=%Line%" 
echo(!Line:*:=!>>"%OUTPUT_H%" 
endlocal 
goto :EOF 

Die bereitgestellte Lösung übergibt die Zeile, die von der Datei gelesen wird, an eine weitere Subroutine. Die übergebene Zeile wird zuerst der Umgebungsvariablen Line im Unterprogramm ExpandLine zugewiesen.

Next Umgebungsvariablen sofortige Expansion verwenden, werden über die Befehlszeile erweitert:

call set "Line=%Line%" 

Nach dieser Befehlszeile die Umgebungsvariable Line hat bei der ersten Ausführung der Haupt FOR Schleife den String-Wert:

#define BLE_UUID_!SERVICE_NAME_UC!_!CHARACTERISTIC_NAME_UC[1]!_CHAR !CHARACTERISTIC_UUID[1]! 

Jetzt ist die verzögerte Erweiterung aktiviert, und diese Zeile wird erneut erweitert, indem zusätzlich eine verzögerte Erweiterung verwendet wird, bevor die zweifach erweiterte Zeile in die Ausgabedatei gedruckt wird.

Ich bin ganz sicher, dass das, was Sie wirklich erreichen wollen viel leichter getan werden könnte, wie unter dem demonstriert auslässt [%INDEX%] in Datei DefCharUUID.txt vollständig:

@echo off 
setlocal EnableExtensions 
set "NUMBER=3" 
set "SERVICE_NAME_UC=SECURITY" 
set "CHARACTERISTIC_NAME_UC[1]=RELAY_CMD" 
set "CHARACTERISTIC_NAME_UC[2]=RELAY_STATUS" 
set "CHARACTERISTIC_NAME_UC[3]=CONFIG" 
set "CHARACTERISTIC_UUID[1]=0x4800" 
set "CHARACTERISTIC_UUID[2]=0x4801" 
set "CHARACTERISTIC_UUID[3]=0x4802" 
set "INPUT_HEADER_PATH=%TEMP%" 
set "OUTPUT_H=%TEMP%\output.h" 
del "%OUTPUT_H%" 2>nul 
echo #define BLE_UUID_!SERVICE_NAME_UC!_!CHARACTERISTIC_NAME_UC!_CHAR !CHARACTERISTIC_UUID!>"%INPUT_HEADER_PATH%\DefCharUUID.txt" 

setlocal EnableDelayedExpansion 
for /L %%I in (1,1,%NUMBER%) do (
    set "CHARACTERISTIC_NAME_UC=!CHARACTERISTIC_NAME_UC[%%I]!" 
    set "CHARACTERISTIC_UUID=!CHARACTERISTIC_UUID[%%I]!" 
    for /F "delims=" %%L in ('%SystemRoot%\System32\findstr.exe /N "^" "%INPUT_HEADER_PATH%\DefCharUUID.txt"') do (
     set "Line=%%L" 
     echo(!Line:*:=!>>"%OUTPUT_H%" 
    ) 
) 
endlocal 

type "%OUTPUT_H%" 
del "%OUTPUT_H%" 
del "%INPUT_HEADER_PATH%\DefCharUUID.txt" 
endlocal 

Einige weitere Hinweise:

GOTO ist der Befehl und :EOF ist der Parameter. Schreiben Sie sie nicht zusammen, obwohl der Windows-Befehlsinterpreter nach dem Anwenden einer Fehlerkorrektur auch GOTO:EOF behandelt.

Es ist ratsam, andere Skripte oder Anwendungen wie FINDSTR mit vollständigem Pfad und Dateierweiterung in einer Batch-Datei verweist die Batch-Datei unabhängig von aktuellen Werten der lokalen Umgebungsvariablen PATHEXT und PATH so viel wie möglich zu machen.

Schließen Sie alle Datei-/Verzeichnisreferenzen in doppelte Anführungszeichen ein, auch wenn sie nicht unbedingt mit den aktuellen Datei-/Verzeichnisnamen/Pfaden benötigt werden, denn wer kennt wirklich die Datei-/Verzeichnisnamen/Pfade in Zukunft.

Verwandte Themen