所以这与此有关 compare #defines in two C files using a batch file 但不同的是: 系统是Win 7(没有Linux命令)。 我有2个文件,内容如
Fil1.c
#define V1 6
...
int Var[V1] ;
******************************
Fil2.c
ifdef USE_V1
#define V1 6
#else
#define V1 5
#endif
我需要在批处理文件中比较V1和V2,如果它们不匹配则抛出错误。 解决方案
for /f "tokens=3" %%A in ('find "#define V1" "Fil1.c"') DO (
set Var1=%%A)
for /f "tokens=3" %%A in ('find "#define V1" "Fil2.c") DO (
set Var2=%%A)
if "%VAR1%" neq "%VAR2%" goto Error2
当 USE_V1 预处理器设置为0时,运行良好。但是,当设置为1时, File2.c 中的 V1 仍然读取值5 ,因为 findtsr 找到2次 #define ,并获得最后一次。
是否有一种方法让findtr只读取#define的第一次或第二次出现(我可以根据GOTO指定,其中我读取VS项目xml中定义的USE_V1并决定我需要执行哪些findtr,哪个先读取出现或读取第二个。)
例如,我可以尝试:
TYPE nul >%tmpPth%
findstr /N /C:"#define V1" "Fil2.c" > %tmpPth%
将以下内容写入tmp.txt
46:#define V1 6
49:#define V1 5
然后,我应该能够使用find / findstr从第一行或第二行读取令牌3。 我已经看到了堆栈溢出的解决方案([Batch file to output last line of findstr 2),它只读取/打印最后一次出现的 搜索字符串,但我需要解决方案,我可以选择我需要重新运行搜索的匹配结果中的哪一行,而不仅仅是打印,而是从行结果中提取标记。
更新:我能够做到以下几点:
set USE_V1="0"
for /f "delims= " %%A in ('findstr /C:"USE_V1" %VCProjPath%') DO (
set USE_V1="1")
set Var3="0"
for /f "tokens=3" %%A in ('find "#define V1" "Fil1.c"') DO (
set Var1=%%A)
if %USE_V1% equ "1" goto USE_V1_USED
for /f "tokens=3" %%A in ('find "#define V1" "Fil2.c"') DO (
set Var2=%%A)
goto MOVEON
:USE_V1_USED
TYPE nul >%tmpPth1%
findstr /C:"#define V1" "Fil2.c" > %tmpPth1%
for /f "tokens=3 delims= " %%A in ('findstr /C:"#define V1" %tmpPth1%') Do (
set Var2=%%A
if "%VAR2%" neq "%VAR3%" goto MOVEON
)
:MOVEON
if "%VAR1%" neq "%VAR2%" goto Error0
我面临的问题是假设 #define V1 在 File1.c 和 File2.c 和
中匹配findstr / C:" #define V1" " Fil2.c" > %tmpPth1%
将tmp文件写为
#define NUMATTR1MEMS 6
#define NUMATTR1MEMS 5
使用
读取for /f "tokens=3 delims= " %%A in ('findstr /C:"#define V1" %tmpPth1%') Do (
set Var2=%%A
if "%VAR2%" neq "%VAR3%" goto MOVEON
)
将两个文件中的%VAR2%视为
如图所示,对应于从临时文件读取的第一行的第二个值具有额外的空格,因此,即使值在数值上匹配,匹配这些的命令也会失败。
那么,有没有办法将 findstr op重定向到文本文件而不会在行结尾处留下额外的空白?
感谢
sedy
答案 0 :(得分:0)
让我们一步一步地完成相当多的任务......
首先,让我们集中精力检索USE_V1
的定义。据我所知,您有一个包含USE_V1
的项目定义文件;如果该文件中存在USE_V1
字面意思,则认为是定义的,否则不是。
以下代码段搜索USE_V1
并设置%VVALGLOB%
(如果找到,我会放置几个set
语句,以便在一个地方初步设置所有内容):
@echo off
rem global project definitions
set FILEPROJ="\path\to\project\file"
set VNAMGLOB=USE_V1
set VVALGLOB=
rem seek %VNAMGLOB% in project file and set %VVALGLOB% if found
for /F %%A in ('findstr /L /I "%VNAMGLOB%" %FILEPROJ%') do (
set VVALGLOB=1
)
接下来是从V1
中提取变量Fil1.c
的值。在这里,我假设总是 #define
指令的第一个出现是要关注的那个:
rem definition of data of file 1
set FILE1="Fil1.c"
set VNAM1=V1
set VVAL1=
rem processing file 1, always take FIRST occurrence of "#define"
for /F "tokens=3" %%A in ('findstr /R /I /C:"^ *#define *%VAR1%" %FILE1%') do (
set /A "VVAL1=%%A"
goto :CONT1
)
:CONT1
我在这里使用set /A
而不是set
来将收集的值视为数字。
现在让我们从V1
有条件地提取Fil2.c
的值:在这里,我检查%VVALGLOB%
是否已定义(记住它是在USE_V1
定义的时候);如果是,则执行#define
指令的第一次次出现;否则,检查 last 一个:
rem definition of data of file 2
set FILE2="Fil2.c"
set VNAM2=V1
set VVAL2=
rem processing file 2, take FIRST OR LAST occurrence of "#define" conditionally
for /F "tokens=3" %%A in ('findstr /R /I /C:"^ *#define *%VAR2%" %FILE2%') do (
set /A "VVAL2=%%A"
if defined VVALGLOB goto :CONT2
)
:CONT2
或者,如果只有第一个或第二个出现的#define
是相关的,那么当有两个以上这样的指令时,{ {1}}部分代码必须替换为以下行:
for /F
从两个文件中提取了正确的值后,我们需要对它们进行比较。为此,我假设他们不能等于零被认为是有效的。如果其中一个或两个都为零,或者它们不相等,则抛出一条消息并退出批处理脚本;否则,批处理脚本继续执行:
rem processing file 2, take FIRST OR SECOND occurrence of "#define" conditionally
for /F "tokens=3" %%A in ('findstr /R /I /C:"^ *#define *%VAR2%" %FILE2%') do (
if defined VVAL2 (
set "VVAL2=%%A"
goto :CONT2
)
set /A "VVAL2=%%A"
if defined VVALGLOB goto :CONT2
)
:CONT2
由于所有值周围都没有双引号,因此会进行数字比较而不是字符串比较。因此,任何尾随空格都无关紧要。
备注:强>
我将rem compare found values for equality in a NUMERICAL manner (both != 0)
if %VVAL1% neq 0 if %VVAL2% neq 0 if %VVAL1% equ %VVAL2% goto :MOVEON
echo They don't match! & exit /B
:MOVEON
rem ...
切换添加到所有/I
次出现,以便进行不区分大小写的搜索。但是,如果findstr
之类的所有变量名都区分大小写,请将其删除
为了搜索V1
指令,我建立了一个正则表达式而不是文字搜索字符串,告诉#define
允许前导空格和关键字与变量名之间的多个空格。
正如上面已经提到的,我将变量(findstr
)值零处理为无效,以避免出现整数以外的值的问题。例如,如果文件中V1
是字符串V1
,则批处理脚本会显示abc
。