解析多个文本文件并将其重新创建为设置模板

时间:2013-06-07 10:31:18

标签: parsing batch-file

我在批量编程方面不是很有经验。我有点捣乱各种代码,但它并不像我想要的那样工作。

这是问题所在。日志文件在目录中创建。有些是多个条目,有些是单个条目。它们都遵循特定的模式。 F.ex。

    START STRING 1234
    NAME1 ADRESS1 ETC
    NAME2 ADRESS2 ETC
    NAME3 ADRESS3 ETC

有时在单个文件中有多个名称条目,有时它只是一个条目。所有文件都有起始字符串。我需要做的是解析这些日志文件并在另一个目录中重新创建它们,文件中每个名称一个文件,每个文件都有一个命名文件的格式。使用上面的例子,它将创建3个文件,每个文件看起来像这样:

    START STRING
    NAME ADRESS ETC

这是代码sofar。它有点工作..除非目录中有多个日志文件,我最终只有几个条目,其中只有两个START STRING,我需要避免。换句话说,我需要单独浏览每个日志文件,而不是像我想象的那样,将所有日志文件视为一个单独的大文本文件。

    @Echo off
    @setlocal enableextensions enabledelayedexpansion


    :::First find out how many lines a file has.
    Set _File=*.log
    Set /a _Lines=0
    For /f %%j in ('Type %_File%^|Find "" /v /c') Do Set /a _Lines=%%j
    set /a "linecount= _Lines"


    :::Grab the first line always and then create a new file depending on how many         lines the file contained
    :LOOP
    if %linecount% GEQ 2 ( 
        set /a "linecount = linecount - 1"
        set lines=1 %linecount%
        set curr=1
            for /f "delims=" %%a in ('type *.log') do (
                    for %%b in (!lines!) do (
                    if !curr!==%%b echo %%a >> c:\temp\logs\%linecount%.log
                    )
                set /a "curr = curr + 1"
            )
    )
    if %linecount% GEQ 2 (GOTO LOOP)
    endlocal

我很确定有更聪明的方法可以做到这一点,但这是我已经得到的。想知道我是否可以简单地匹配起始字符串并以某种方式将其删除,而不删除第一行,或者最好避免将双重启动字符串全部放在一起。

2 个答案:

答案 0 :(得分:1)

您的问题描述不明确,但从您的代码判断,我假设您只想在新文件夹中重新创建每个日志文件,只保留每个原始文件的前两行。

如果是这样,那么这就是你所需要的:

@echo off
setlocal
set "sourceMask=.\*.log"
set "targetPath=test"
set "keepCount=2"

for %%F in ("%sourceMask%") do (
  <"%%~F" (
    for /l %%N in (1 1 %keepCount% ) do (
      set "ln="
      set /p "ln="
      echo(!ln!
    )
  ) >"%targetPath%\%%~nxF"
)

限制:

  • 行必须以<CR><LF>结尾(Windows样式),而不是<LF>(unix样式)
  • 行不得超过1021个字节(不包括行终止符)
  • 尾随控制字符将从该行中删除。

以上解决方案无法满足基于评论的OP需求


编辑:尝试2基于OP的提交中的精炼要求(未经测试)

空行将被忽略 - 可能是一件好事。

该代码旨在成为rubust。它应该处理字符串中的任何字符,包括以;(或任何其他字符)开头的行和包含!的行。这就是奇数FOR / F选项字符串和延迟扩展切换的原因。

行长度限制为大约8191个字节。

@echo off
setlocal disableDelayedExpansion
set "sourceMask=.\*.log"
set "targetPath=test"
set "targetName=0"

for %%F in ("%sourceMask%") do (
  set "startString="
  for /f usebackq^ delims^=^ eol^= %%A in ("%%~F") do (
    if not defined startString (set "startString=%%A") else (
      set "nameString=%%A"
      set /a targetName+=1
      setlocal enableDelayedExpansion
      (
        echo(!startString!
        echo(!nameString!
      ) >"!targetPath!\!targetName!.log"
      endlocal
    )
  )
)

答案 1 :(得分:0)

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION 
:: directories in question
SET destdir=c:\destdir
SET sourcedir=c:\sourcedir
SET /a filecount=0
:: process each .log file in source
FOR %%f IN (%sourcedir%\*.log) DO (
 SET "startline="
 FOR /f "usebackqdelims=" %%i IN ("%%f") DO (
  IF DEFINED startline (
   CALL :nextfname
   >>!filename! ECHO(%%i
  ) ELSE (
   SET "startline=%%i"
  )
 )
)

GOTO :eof
::
:: Write the header line to the next NEW destination file
::
:nextfname
SET "filename=%destdir%\%filecount%.log"
SET /a filecount+=1
IF EXIST %filename% GOTO nextfname
>>%filename% ECHO(%startline%
GOTO :eof

这应该做你想要的 - IIUC,来自源中的每个.log文件,在目标中创建一个包含2行的文件 - 来自相应源日志文件的起始行之后的名称行。 (好吧,如果这不是你想要的,那就是这个例程会做的......)

  • 它处理源目录中的每个文件名,应用于%%f
  • 在每个新文件名中,清除startline
  • 将第一行的内容分配给startline
  • 每个剩余的行,
    • filename设置为目标中的新文件名并将起始行写入其中
    • %%i中的名称行输出到生成的文件名。

请注意,ENABLEDELAYEDEXPANSION允许!filename!引用filename的内容,因为它在FOR...%%i...

的上下文中发生了变化

例程:nextfilename在其自己的上下文中,因此%var%以其更熟悉的含义使用。例程只是从filecount建立一个名称并递增filecount,检查文件是否已经存在,并重复直到找到一个全新的文件名。然后将标题行写入该文件名。