首页 文章

如何计算文本文件中的行数并使用批处理脚本将值存储到变量中?

提问于
浏览
42

我想计算文本文件中的行数,然后将值存储到环境变量中 . 计算行数的命令是

findstr /R /N "^" file.txt | find /C ":"

我提到了问题How to store the result of a command expression in a variable using bat scripts?然后我试过了,

set cmd="findstr /R /N "^" file.txt | find /C ":" "

我收到错误消息,

FIND: Parameter format not correct

我怎么能摆脱这个错误 .

14 回答

  • 15

    您可以使用FOR / F循环将输出分配给变量 .

    我使用 cmd-variable ,因此不需要转义cmd-string中的管道或其他字符,因为延迟扩展将字符串"unchanged"传递给FOR-Loop .

    @echo off
    cls
    setlocal EnableDelayedExpansion
    set "cmd=findstr /R /N "^^" file.txt | find /C ":""
    
    for /f %%a in ('!cmd!') do set number=%%a
    echo %number%
    
  • 2

    有一种比所有其他方法简单得多的方法 .

    find /v /c "" filename.ext
    

    显然,从传统的MS-DOS时代保留 . 更多信息:http://blogs.msdn.com/b/oldnewthing/archive/2011/08/25/10200026.aspx

    使用示例:

    adb shell pm list packages | find /v /c ""
    

    如果您的Android设备已连接到您的PC并且您的路径上有Android SDK,则会打印出设备上安装的应用程序数量 .

  • 3

    受以前帖子的启发,这样做的方式更短:

    CMD.exe
    C:\>FINDSTR /R /N "^.*$" file.txt | FIND /C ":"
    

    行数

    试试吧 . 它适用于我的控制台 .

    已编辑:

    (删除了“$”标志)

    FINDSTR /R /N "^.*" file.txt | FIND /C ":"
    

    $将数字减少1,因为它接受第一行作为字段名称,然后计算行数 .

  • 81

    试试这个:

    @Echo off
    Set _File=file.txt
    Set /a _Lines=0
    For /f %%j in ('Find "" /v /c ^< %_File%') Do Set /a _Lines=%%j
    Echo %_File% has %_Lines% lines.
    

    它消除了额外的FindStr,不需要扩展 .


    • 编辑使用ChrisJJ的重定向建议 . 删除 TYPE 命令使其快三倍 .
  • 4

    @Tony:你甚至可以摆脱 type %file% 命令 .

    for /f "tokens=2 delims=:" %%a in ('find /c /v "" %_file%') do set /a _Lines=%%a
    

    对于长文件,这应该更快 .

  • 2

    我通常使用更像这样的东西 for /f %%a in (%_file%) do (set /a Lines+=1)

  • 0

    您不需要使用find .

    @echo off
    set /a counter=0
    for /f %%a in (filename) do set /a counter+=1
    echo Number of lines: %counter%
    

    这将迭代文件中的所有行,并将每行的计数器变量增加1 .

  • 4

    我发现这个解决方案最适合创建一个维护自己的日志文件:

    setlocal enabledelayedexpansion
    SET /A maxlines= 10
    set "cmd=findstr /R /N "^^" "filename.txt" | find /C ":""
     for /f %%a in ('!cmd!') do set linecount=%%a
    GOTO NEXT
    
    :NEXT 
     FOR /F %%A IN ("filename.txt") DO ( 
      IF %linecount% GEQ %maxlines% GOTO ExitLoop
      echo %clientname% %Date% %Time% >> "filename.txt")
     EXIT
    
    :ExitLoop
     echo %clientname% %Date% %Time% > "filename.txt"
     EXIT
    

    包含的环境变量是%clientname%远程客户端的计算机名%%Date%是当前日期,%Time%是当前时间 . :获取文件中的行数后调用NEXT . 如果文件行数大于%maxlines%变量,则转到:EXITLOOP,它覆盖文件,创建一个带有第一行信息的新文件 . 如果它小于%maxlines%变量,它只是将该行添加到当前文件 .

  • 33
    for /f "usebackq" %A in (`TYPE c:\temp\file.txt ^| find /v /c "" `) do set numlines=%A
    

    在批处理文件中,使用%% A而不是%A

  • 7

    只是:

    c:\>(for /r %f in (*.java) do @type %f ) | find /c /v ""
    

    字体:https://superuser.com/questions/959036/what-is-the-windows-equivalent-of-wc-l

  • 1

    在下面的代码中,变量名称是 SalaryCountTaxCount

    @ECHO OFF    
    echo Process started, please wait...    
    for /f %%C in ('Find /V /C "" ^< "D:\Trial\Salary.txt"') do set SalaryCount=%%C    
    echo Salary,%SalaryCount%
    for /f %%C in ('Find /V /C "" ^< "D:\Trial\Tax.txt"') do set TaxCount=%%C
    echo Tax,%TaxCount%
    

    现在,如果您需要将这些值输出到csv文件,则可以使用以下代码 .

    @ECHO OFF
    cd "D:\CSVOutputPath\"
    echo Process started, please wait...
    echo FILENAME,FILECOUNT> SUMMARY.csv
    for /f %%C in ('Find /V /C "" ^< "D:\Trial\Salary.txt"') do set Count=%%C
    echo Salary,%Count%>> SUMMARY.csv
    for /f %%C in ('Find /V /C "" ^< "D:\Trial\Tax.txt"') do set Count=%%C
    echo Tax,%Count%>> SUMMARY.csv
    

    > 将覆盖文件的现有内容, >> 将新数据附加到现有数据 . CSV将在 D:\CSVOutputPath 中生成

  • 0

    您可以将 type 的输出传递到 for /f 循环的 in(…) 子句中的 find

    for /f %%A in ('
        type "%~dpf1" ^| find /c /v ""
    ') do set "lineCount=%%A"
    

    但是管道开始了一个子壳,这会减慢速度 .

    或者,您可以将文件中的输入重定向到 find ,如下所示:

    for /f %%A in ('
        find /c /v "" ^< "%~dpf1"
    ') do set "lineCount=%%A"
    

    但是如果文件以一个或多个空行结束,这种方法会给你一个比实际行数少1的答案,如counting lines in a file中已故的foxidrive所述 .

    然后再次,你可以尝试:

    find /c /v "" example.txt
    

    麻烦的是,上面命令的输出如下所示:

    ---------- EXAMPLE.TXT: 511
    

    您可以在冒号上拆分字符串以获取计数,但如果文件名具有完整路径,则可能有多个冒号 .

    这是我对这个问题的看法:

    for /f "delims=" %%A in ('
        find /c /v "" "%~1"
    ') do for %%B in (%%A) do set "lineCount=%%B"
    

    这将始终将计数存储在变量中 .

    只是最后一个小问题... find 将空字符视为换行符 . 因此,如果偷偷摸摸的空值悄悄进入您的文本文件,或者如果您想计算Unicode文件中的行,则此答案不适合您 .

  • 0

    下面的 :countLines 子程序接受两个参数:变量名称;和文件名 . 计算文件中的行数,结果存储在变量中,结果传递回主程序 .

    该代码具有以下功能:

    • 使用Windows或Unix行结尾读取文件 .

    • 处理Unicode以及ANSI / ASCII文本文件 .

    • 应对极长的线条 .

    • 不被空字符所迷惑 .

    • 读取空文件时出错 .

    • 超出批量最大限制 (31^2)-1 的计数 .

    @echo off & setLocal enableExtensions disableDelayedExpansion
    
    call :countLines noOfLines "%~1" || (
        >&2 echo(file "%~nx1" is empty & goto end
    ) %= cond exec =%
    echo(file "%~nx1" has %noOfLines% line(s)
    
    :end - exit program with appropriate errorLevel
    endLocal & goto :EOF
    
    :countLines result= "%file%"
    :: counts the number of lines in a file
    setLocal disableDelayedExpansion
    (set "lc=0" & call)
    
    for /f "delims=:" %%N in ('
        cmd /d /a /c type "%~2" ^^^& ^<nul set /p "=#" ^| (^
        2^>nul findStr /n "^" ^&^& echo(^) ^| ^
        findStr /blv 1: ^| 2^>nul findStr /lnxc:" "
    ') do (set "lc=%%N" & call;) %= for /f =%
    
    endlocal & set "%1=%lc%"
    exit /b %errorLevel% %= countLines =%
    

    我知道它看起来很可怕,但它涵盖了大多数边缘情况并且速度惊人 .

  • -1

    完美的解决方案是:

    FOR /F %%i IN ('FIND /C /V "" ^< "Text file.txt"') DO SET Lines=%%i
    

相关问题