【问题标题】:Batch file to count occurrences用于计数出现次数的批处理文件
【发布时间】:2013-12-27 16:18:33
【问题描述】:

我有一个这样的纯文本文件:

...
... TYPE: alm01, ........
...
...
...
... TYPE: almBB, ........
...
...
... TYPE: out, ......
...
... TYPE: in, ......
... TYPE: almBB, ........
... TYPE: out, ......
... TYPE: out, ......

(省略号是一行中的东西)

所以使用批处理文件或cmd命令(必要时使用管道)我想统计并输出每种类型的出现次数,从上面的示例中,我想输出:

alm01 1
almBB 2
out 3
in 1

我该怎么做?

第一次尝试:(不工作)

@echo off
setlocal enableextensions enabledelayedexpansion

rem Configuration
set "file=test.log"

rem Clean environment
for /f "tokens=1 delims==" %%v in ('set _type_ 2^>nul') do set "%%v="

rem Search required lines
for /f "tokens=*" %%l in ('findstr "TYPE:" "%file%"') do (

    rem Now we have the whole line

    set "t=%%l"

    rem Remove the prefix of the line
    set "t=%t:*TYPE: =%"
    set "t=%t:~1%"

    rem Remove the suffix of the line (from comma to end) and 
    rem increment counter of type
    for /f "tokens=1 delims=," %%t in ('echo %t%') do set /a "_type_%%t+=1"
)

rem Enumerate find types and echo type and number of occurrences
rem The inner loop is to allow underscores inside type
for /f "tokens=1,* delims=_" %%a in ('set _type_ 2^>nul') do (
    for /f "tokens=1,2 delims==" %%v in ("%%a") do echo %%v %%w
)

rem Clean and exit
endlocal
exit /b

【问题讨论】:

  • 这在 bash 中很容易。 MS-DOS是指pre-Win32系统,还是只是命令提示符(cmd.exe)?
  • 是的,V-X 的问题很关键。你真的是说 MS-DOS 批处理吗?还是您正在使用 Windows 批处理? MS-DOS 功能受到更多限制。
  • @dbenham 我想用一个 bat 文件执行此操作,并从 windows 命令 (cmd) 提示符执行它。

标签: windows batch-file


【解决方案1】:
@echo off
    setlocal enableextensions disabledelayedexpansion

    rem Configuration
    set "file=plaintext.txt"

    rem Clean environment
    for /f "tokens=1 delims==" %%v in ('set _type_ 2^>nul') do set "%%v="

    rem Search required lines
    for /f "tokens=*" %%l in ('findstr "TYPE:" "%file%"') do (

        rem Now we have the whole line
        set "t=%%l"

        rem Can't handle it inside the for loop. Go out to do it
        call :handleType
    )

    rem Enumerate find types and echo type and number of occurrences
    rem The inner loop is to allow underscores inside type
    for /f "tokens=1,* delims=_" %%a in ('set _type_ 2^>nul') do (
        for /f "tokens=1,2 delims==" %%v in ("%%b") do echo %%v %%w
    )

    rem Clean and exit
    endlocal
    exit /b

:handleType
    rem Remove the prefix of the line
    set "t=%t:*TYPE: =%"
    rem Remove spaces (not needed as OP stated and giving problems)
    set "t=%t: =%"

    rem Remove the suffix of the line (from comma to end) and 
    rem increment counter of type
    for /f "tokens=1 delims=," %%t in ("%t:"=%") do set /a "_type_%%~t+=1"

    goto :EOF

已编辑

问题是实际文件在行内包含一些特殊字符(至少!),并且这些字符由于启用了延迟扩展而被扩展,产生了OP指示的错误。

要处理它,延迟扩展需要关闭,但由于我们在 for 循环中读取文件,要访问变量的更改值,延迟扩展需要打开,所以,将其关闭并移动用于类型管理的代码行到 for 循环外的子例程。

【讨论】:

  • 我刚刚测试过它,它不工作。它说操作员错过了。删除该行的前缀不起作用。你在脚本中也有一些错误。请参阅我发布的已纠正错误的帖子。无论如何,它不起作用。
  • 对不起,它不起作用,同样的错误:“操作员错过了”。此外,我认为你有一些语法错误:当枚举找到的类型和回显类型和出现次数时,在内循环中它应该是 %%a 而不是 %%b。此外,当在句柄类型中删除行的前缀时,在执行设置后的行开头,它会保留一个空格,您应该使用例如设置“t=%t:~1%”来删除该空格。最后,最后一行转到:EOF,脚本中的 EOF 标记在哪里?非常感谢。
  • @user304602:错误发生在哪一行? %%b 没问题,外部用于使用tokens=1,*_type_(在%%a)与行的其余部分(在%%b)分开,内部用于将类型(在%%v)与计数(在%%w)。空格(一个空格)包含在前缀删除中。如果有更多空间,请根据需要进行调整。 :eof 是启用扩展时可用的“预定义”标签,表示End Of File。有关说明,请参阅 goto /?
  • @user304602:您的“TYPE”值到底如何?它可以有什么价值?
  • 现在可以正常使用了,抱歉。您的脚本中只有一个错误:在句柄类型主体中,在 for 循环中,而不是 ("%t:"=%") 是 ("%t: =%")。请更正它。你能解释一下吗为什么在内部循环中枚举找到的类型是 %%b 而不是 %%a?我不明白。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-09
  • 1970-01-01
  • 1970-01-01
  • 2012-11-25
  • 2014-02-26
  • 2013-03-01
相关资源
最近更新 更多