【问题标题】:How to count no of lines in text file and store the value into a variable using batch script?如何计算文本文件中的行数并使用批处理脚本将值存储到变量中?
【发布时间】:2011-08-05 14:31:29
【问题描述】:

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

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

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

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

我收到错误消息,

FIND:参数格式不正确

我怎样才能摆脱这个错误。

【问题讨论】:

    标签: windows batch-file cmd


    【解决方案1】:

    你也可以试试

    set n=0 & for /f "tokens=*" %a in (text.txt) do set/a n=!n!+1
    echo !n!
    

    【讨论】:

    • a) 不计算空行 b) 速度非常慢 c) 多年前有几个相同或非常相似的答案。
    【解决方案2】:

    对于一个在他的 Windows 上有 git bash 的人来说,一个惊喜是:只是普通的旧 linux wc -l <filename> 在那里可以为你工作

    【讨论】:

      【解决方案3】:

      也可以用通配符*标记,方便分组文件计数。

      Z:\SQLData>find /c /v "" FR_OP133_OCCURENCES_COUNT_PER_DOCUMENTS_*.txt
      

      结果

      --------- FR_OP133_OCCURENCES_COUNT_PER_DOCUMENTS_AVIFRS01_V1.TXT:2041

      --------- FR_OP133_OCCURENCES_COUNT_PER_DOCUMENTS_AVIOST00_V1.TXT:315938

      --------- FR_OP133_OCCURENCES_COUNT_PER_DOCUMENTS_AVIFRS00_V1.TXT:0

      --------- FR_OP133_OCCURENCES_COUNT_PER_DOCUMENTS_CNTPTF00_V1.TXT:277

      【讨论】:

      • 您回答了一些其他问题,当前问题是如何将结果存储到变量中
      • 嗯,这是为了扩展已经提出的答案。另外,您的回答效率最低。
      【解决方案4】:

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

      find /v /c "" filename.ext
      

      显然是遗留下来的 MS-DOS 时代。更多信息在这里:https://devblogs.microsoft.com/oldnewthing/20110825-00/?p=9803

      使用示例:

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

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

      【讨论】:

      • 不满足将值存储在环境变量中的要求。
      • 干净且相当高效。不错。
      • @ChrisJJ 如果您设置了一个只执行:SET __ for /f "tokens=*" %%A in ('%2 %3 %4 %5 %6 %7 %8 %9') do Set "%1=%%A" __ Exit \B 的子例程(或.bat),您可以将任何单行输出程序保存到var 中,只需像这样调用它; Call :SET varName find /v /c "" filename.ext(其中 __ 是换行符)
      • 我不知道为什么这个答案有这么多的赞成票。较早的响应包括相同的find 命令,但还根据要求在变量中提供了计数。
      • 要在变量LINE中获取结果,请使用for /F "usebackq tokens=3 delims=:" %%L in (`find /v /c "" %logfile%`) do set lines=%%L
      【解决方案5】:

      完美的解决方案是:

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

      【讨论】:

      • 这是一个很好的解决方案,但是对于这个问题已经多次给出了相同的答案。最古老、相同的答案来自 2012 年
      • 但更简单,更有逻辑。
      • @TundePizzle 答案是正确的,但重复发布的好处在哪里?
      • @jeb,请给我们看副本。我没有在相同的上下文中看到任何内容。你的行为让我感到困惑。
      • Tunde-Pizzle:重复的是这部分,已经在@jeb的回答中给出:for /f %%a in ('!cmd!') do set number=%%a
      【解决方案6】:

      只是:

      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

      【讨论】:

        【解决方案7】:

        你不需要使用 find。

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

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

        【讨论】:

        • 但不计算空行和分号开头的行
        • 而且速度很慢。 find /c /v "" 效率非常
        【解决方案8】:

        下面的:countLines 子例程接受两个参数:变量名;和一个文件名。统计文件的行数,结果存入变量,结果传回主程序。

        该代码具有以下特点:

        • 读取带有 Windows 或 Unix 行结尾的文件。
        • 处理 Unicode 以及 ANSI/ASCII 文本文件。
        • 处理极长的行。
        • 不会被空字符吓到。
        • 读取空文件时引发错误。
        • 计数超出了 (31^2)-1 的 Batch max int 限制。
        @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 =%

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

        【讨论】:

        • 一个被低估的答案,我将它与其他批处理文件进行了比较,并将它们用于包含数百万个密码的文件,令我惊讶的是,这个宝贝在大约 5-6 秒内给了我答案,而其他批处理文件给出了至少在 15 到 20 秒内给我答案。我投赞成票
        【解决方案9】:

        您可以在for /f 循环的in(…) 子句内将type 的输出通过管道传输到find

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

        但是管道启动了一个子shell,这会减慢速度。

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

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

        但是,如果文件以一个或多个空行结尾,如 counting lines in a file 中已故的 foxidrive 所梳理的那样,这种方法会给您的答案比实际行数少 1。

        再一次,你总是可以尝试:

        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 文件中的行数,那么这个答案不适合您。

        【讨论】:

          【解决方案10】:
          for /f "usebackq" %A in (`TYPE c:\temp\file.txt ^| find /v /c "" `) 设置 numlines=%A

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

          【讨论】:

            【解决方案11】:

            试试这个:

            @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 命令使其速度提高了三倍。

            【讨论】:

            • 谢谢。这得到了我的投票:)。但我发现不需要 type 命令。 For /f %%j in ('Find "" /v /c ^&lt; %_File%') Do Set /a _Lines=%%j
            • 嗨 ChrisJJ,您对 &lt; 和我的 TYPE | 的使用等同于同一件事。
            【解决方案12】:

            在下面的代码中,变量名是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
            

            &gt; 将覆盖文件的现有内容,&gt;&gt; 将新数据附加到现有数据中。 CSV 将在 D:\CSVOutputPath

            中生成

            【讨论】:

              【解决方案13】:

              受前几篇文章的启发, 一种更短的方法:

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

              行数

              试试看。它适用于我的控制台。

              已编辑:

              (去掉“$”符号)

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

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

              【讨论】:

              • 如果文件有很孤的行,这会产生很多错误,但最终输出仍然正确
              【解决方案14】:

              我发现此解决方案最适合创建可自我维护的日志文件:

              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% 变量,它只会将该行添加到当前文件中。

              【讨论】:

                【解决方案15】:

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

                【讨论】:

                • 大文件速度慢并且不计算空行(它们被for /f 忽略,因此计数器不会增加)
                【解决方案16】:

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

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

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

                【讨论】:

                • 这更快,但使用这种方法,如果文件名包含冒号(例如,“c:\temp\file.txt”),它会在冒号处解析该字符串,而不是命令的结果。
                • for %%a in ("%file%") do for /f "tokens=3 delims=:" %%b in ('find /v /c "" "%%~fa"') do set lines=%%b 处理短文件名和长文件名。
                【解决方案17】:

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

                我使用cmd-variable,因此不需要转义 cmd 字符串中的管道或其他字符,因为延迟扩展会将字符串“未更改”传递给 FOR 循环。

                @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%
                

                【讨论】:

                • 非常感谢,我在“questions/1350225”中使用它,效果很好!
                • 非常感谢!我只是在这里尝试计算目录中所有文件的行数,它也运行良好。只需将file.txt 替换为*.txt 并等待。 :)
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2017-12-05
                • 2019-08-16
                • 1970-01-01
                • 2017-01-22
                • 2015-03-23
                • 2017-08-21
                • 1970-01-01
                相关资源
                最近更新 更多