我想将命令的结果存储在批处理脚本中的for循环中的变量中。我想循环遍历一系列.sql文件,计算每个文件包含的行数,并总结行数。
到目前为止,这是我的尝试:
@echo off
setlocal ENABLEDELAYEDEXPANSION
set /a count=0
set /a t=0
for /f %%a in ('dir /b *.sql') do (
@echo %%a <- THIS PRINTS THE FILE NAME
@set t=findstr /r /n "^" %%a | find /C ":" <- THIS IS INCORRECT
echo %t% <- I WANT TO PRINT THE LINE COUNT FOR THE FILE
@set /a count+=%t% <- INCREASE THE COUNTER
)
echo %count% <- PRINT TOTAL LINE COUNT
当我跑步时
findstr /r /n "^" *.sql | find /C ":"
在命令窗口中它可以工作,我知道我可以将它用于最终目标,但这个问题是关于变量赋值。
我的错误在哪里?变量t
始终被赋值为0。
更新 :(仍然无效)
@echo off
setlocal ENABLEDELAYEDEXPANSION
set /a count=0
set /a t=0
for /f %%a in ('dir /b *.sql') do (
@echo %%a
for /L %%b in ('findstr /r /n "^" %%a ^| find /C ":"') do (
set /a count+=%%b
)
)
echo !count!
对于任何有兴趣在此阅读的人,这是最终的(工作版):
@ECHO off
SETLOCAL ENABLEDELAYEDEXPANSION
SET /a count=0
SET /a t=0
for /f %%a in ('dir /b *.sql') do (
@echo %%a
for /f %%b in ('findstr /r /n "^" %%a ^| find /C ":"') do (
set t=%%b
)
ECHO !t!
@SET /a count+=!t!
)
ECHO "Total:" !count!
答案 0 :(得分:2)
@set t=findstr /r /n "^" %%a | find /C ":" <- THIS IS INCORRECT
不起作用。它将变量t
设置为字符串findstr /r /n "^" %%a
,并使用set
过滤| find /C ":"
命令的输出(不输出任何内容),其中无条件地计算零冒号。 / p>
最好的方法是:
for /f %%x in ('findstr /r /n "^" %%a ^| find /C ":"') do set t=%%x
编辑我非常专注于修复您的代码,我并没有真正意识到,您只想计算所有* .SQL文件的所有行。这很容易。无需延迟扩张:
set count=0
for /f %%a in ('type *.sql 2^>nul ^| find /n /v ""') do set /a count+=1
echo %count%
2>nul
阻止type
将文件名打印到屏幕上。
<强> EDIT2 强>
我的解决方案有203个文件,总共47763行需要大约24秒。 Aschipfl的edit2
解决方案大约有七个毫秒秒。令人印象深刻的...... find /c
必须有一个非常有效的方法来计算线条。
我稍微更改了使用此功能的代码:
set count=0
for /f %%a in ('type *.sql 2^>nul ^| find /c /n /v ""') do set /a count+=%%a
echo %count%
还需要大约7ms。没什么大惊喜,因为它与Aschipfl的代码基本相同 - 只是格式不同。
答案 1 :(得分:2)
不需要使用findstr /N /R "^"
在每行前面加上行号和:
,然后计算包含:
的行数。
要计算文本文件包含的行数,您只需将其重定向到find /C /V ""
,如下所示:
< "\path\to\file.txt" find /C /V ""
要在for
循环中使用此功能,您可以执行以下操作:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set /A COUNT=0
set /A T=0
for /F "eol=| delims=" %%A in ('dir /B "*.sql"') do (
setlocal DisableDelayedExpansion
echo(%%~A
for /F %%B in ('^< "%%~A" find /C /V ""') do (
endlocal
set /A T=%%B
)
echo(!T!
set /A COUNT+=T
)
echo Total: %COUNT%
endlocal
exit /B
切换延迟扩展是为了避免任何!
文件名中的感叹号*.sql
出现问题,否则会被忽略,并会出现错误消息The system cannot find the file specified.
。只有(调试)行echo(!T!
才需要延迟扩展;如果删除它,则可以禁用整个脚本的延迟扩展。
以上是上述脚本的压缩变体,没有任何临时变量T
且禁用了延迟扩展:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A COUNT=0
for /F "eol=| delims=" %%A in ('dir /B "*.sql"') do (
for /F %%B in ('^< "%%~A" find /C /V ""') do (
echo(%%~A: %%B
set /A COUNT+=%%B
)
)
echo TOTAL: %COUNT%
endlocal
exit /B
这是一个使用单个for /F
循环来检索行数的脚本,这样可以find
搜索*.sql
文件,例如find /C /V "" "*.sql"
,然后例如,它的输出看起来像---------- file.sql: 5
,在:
之后将计数分开并总结所有这些。这种方法需要再次推迟扩展:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A COUNT=0
for /F "eol=| delims=" %%A in ('find /C /V "" "*.sql"') do (
set "LINE=%%~A"
echo(%%~A
setlocal EnableDelayedExpansion
set /A T=!LINE:*: =!
for /F "delims=" %%B in ("!T!") do (endlocal & set /A COUNT+=%%B)
)
echo TOTAL: %COUNT%
endlocal
exit /B
是的,还有第二个for /F
循环嵌套,但这是将T
的价值转移到endlocal
障碍所必需的。
这可能是确定多个文件的总行数的最佳解决方案。这允许type
输出所有*.sql
个文件的每一行,然后由find
计算。因此for /F
循环仅迭代一次,因此该脚本的整体性能非常好:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set /A COUNT=0
for /F "delims=" %%A in ('
2^>nul type "*.sql" ^| find /C /V ""
') do (
set /A COUNT+=%%A
)
echo TOTAL: %COUNT%
endlocal
exit /B