从find / findstr结果

时间:2015-08-18 21:29:07

标签: batch-file

所以这与此有关 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%视为

enter image description here 如图所示,对应于从临时文件读取的第一行的第二个值具有额外的空格,因此,即使值在数值上匹配,匹配这些的命令也会失败。

那么,有没有办法将 findstr op重定向到文本文件而不会在行结尾处留下额外的空白?

感谢
sedy

1 个答案:

答案 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