从文本文件中获取不同的值

时间:2012-07-19 21:07:21

标签: text batch-file

我正在使用非常大的FIX消息日志文件。每条消息代表一组由SOH字符分隔的标签。

与MQ消息不同,单个FIX标记(和整体消息)不具有固定长度或位置。日志可以包括不同类型的消息(具有不同数量和标签序列)。

示例(多种消息之一):

07:00:32 -SEND:8=FIX.4.0(SOH)9=55(SOH)35=0(SOH)34=2(SOH)43=N(SOH)52=20120719-11:00:32(SOH)49=ABC(SOH)56=XYZ(SOH)10=075

所以唯一确定的事情如下:(1)带有等号的标签号唯一标识标签,(2)标签由SOH字符分隔。

对于特定的标签(一次只是其中几个,而不是所有标签),我需要得到一个不同值的列表 - 如下所示:

49 = ABC 49 = DEF 49 = GHI ......

输出的格式并不重要。

我非常感谢任何建议和建议。

亲切的问候, Victor O。

2 个答案:

答案 0 :(得分:2)

选项1

下面的批处理脚本具有不错的性能。它有以下限制

  • 检查重复项时忽略大小写。
  • 可能无法正确保留值
  • 中包含=的所有值

编辑 - 我的原始代码根本不支持值=。我通过在变量名中添加额外的SOH字符来减少该限制,并更改了用于解析值的delim。现在,只要在=之前区分唯一值,值就可以包含=。如果值在=之后区分,则只保留一个值。

务必将SOH变量的定义固定在顶部附近。

日志文件的名称作为第一个参数传递,请求的标记列表作为第二个参数传递(用引号括起来)。

@echo off
setlocal disableDelayedExpansion

:: Fix the definition of SOH before running this script
set "SOH=<SOH>"
set LF=^


:: The above 2 blank lines are necessary to define LF, do not remove.

:: Make sure there are no existing tag_ variables
for /f "delims==" %%A in ('2^>nul set tag_') do set "%%A="

:: Read each line and replace SOH with LF to allow iteration and parsing
:: of each tag/value pair. If the tag matches one of the target tags, then
:: define a tag variable where the tag and value are incorporated in the name.
:: The value assigned to the variable does not matter. Any given variable
:: can only have one value, so duplicates are removed.
for /f "usebackq delims=" %%A in (%1) do (
  set "ln=%%A"
  setlocal enableDelayedExpansion
  for %%L in ("!LF!") do set "ln=!ln:%SOH%=%%~L!"
  for /f "eol== tokens=1* delims==" %%B in ("!ln!") do (
    if "!!"=="" endlocal
    if "%%C" neq "" for %%D in (%~2) do if "%%B"=="%%D" set "tag_%%B%SOH%%%C%SOH%=1"
  )
)

:: Iterate the defined tag_nn variables, parsing out the tag values. Write the
:: values to the appropriate tag file.
del tag_*.txt 2>nul
for %%A in (%~2) do (
  >"tag_%%A.txt" (
    for /f "tokens=2 delims=%SOH%" %%B in ('set tag_%%A') do echo %%B
  )
)

:: Print out the results to the screen
for %%F in (tag_*.txt) do (
  echo(
  echo %%F:
  type "%%F"
)

选项2

这个脚本几乎没有任何限制,但速度明显变慢。我可以看到的唯一限制是它不允许以=开头的值(前导=将被丢弃)。

我创建了一个临时的“search.txt”文件,用于FINDSTR / G:选项。由于FINDSTR限制,我使用文件而不是命令行搜索字符串。命令行搜索字符串不能匹配多个字符&gt;十进制128.此外,文字反斜杠的转义规则在命令行上不一致。有关详细信息,请参阅What are the undocumented features and limitations of the Windows FINDSTR command?

必须再次修复SOH定义,第一个和第二个参数与第一个脚本相同。

@echo off
setlocal disableDelayedExpansion

:: Fix the definition of SOH before running this script
set "SOH="
set lf=^


:: The above 2 blank lines are necessary to define LF, do not remove.

:: Read each line and replace SOH with LF to allow iteration and parsing
:: of each tag/value pair. If the tag matches one of the target tags, then
:: check if the value already exists in the tag file. If it doesn't exist
:: then append it to the tag file.
del tag_*.txt 2>nul
for /f "usebackq delims=" %%A in (%1) do (
  set "ln=%%A"
  setlocal enableDelayedExpansion
  for %%L in ("!LF!") do set "ln=!ln:%SOH%=%%~L!"
  for /f "eol== tokens=1* delims==" %%B in ("!ln!") do (
    if "!!"=="" endlocal
    set "search=%%C"
    if defined search (
      setlocal enableDelayedExpansion
      >search.txt (echo !search:\=\\!)
      endlocal
      for %%D in (%~2) do if "%%B"=="%%D" (
        findstr /xlg:search.txt "tag_%%B.txt" || >>"tag_%%B.txt" echo %%C
      ) >nul 2>nul
    )
  )
)
del search.txt 2>nul

:: Print out the results to the screen
for %%F in (tag_*.txt) do (
  echo(
  echo %%F:
  type %%F
)

答案 1 :(得分:1)

试试这个批处理文件。添加日志文件名作为参数。 e.g:

LISTTAG.BAT SOH.LOG

它将显示所有标记ID及其唯一值。 e.g:

9=387
12=abc
34=asb73
9=123
12=xyz

名为tagNNlist.txt的文件(其中NN是标签ID号)将用于查找唯一标签ID和值,但在批次结束时保留为完整的报告。

以下代码中显示的{SOH}文本实际上是 SOH 字符(ASCII 0x01),因此在您复制&amp;粘贴代码后,应将其更改为 SOH 字符。我必须替换该字符,因为它被服务器剥离了。通过键入0001,然后按ALT+X,使用 Wordpad 生成 SOH 字符。副本&amp;使用批处理文件代码将该字符粘贴到记事本中。

需要注意的一点是,代码只会处理从第16列开始的行。示例行中的07:00:32 -SEND:将被忽略。我假设他们都是从那个固定长度的文本开始的。

的变化:

  • 通过标签ID将生成的标签列表文件更改为单独的文件。例如:tag12list.txttag52list.txt

  • 在生成的标记列表文件中删除了标记ID号。例如:12=abc成为abc

LISTTAG.BAT

@echo off
setlocal enabledelayedexpansion
if "%~1" == "" (
  echo No source file specified.
  goto :eof
)
if not exist "%~1" (
  echo Source file not found.
  goto :eof
)
echo Warning! All "tagNNlist.txt" file in current
echo directory will be deleted and overwritten.
echo Note: The "NN" is tag id number 0-99. e.g.: "tag99list.txt"
pause
echo.
for /l %%a in (0,1,99) do if exist tag%%alist.txt del tag%%alist.txt
for /f "usebackq delims=" %%a in ("%~1") do (
  rem *****below two lines strip the first 15 characters (up to "-SEND:")
  set x=%%a
  set x=!x:~15,99!
  rem *****9 tags per line
  for /f "tokens=1,2,3,4,5,6,7,8,9 delims={SOH}" %%b in ("!x!") do (
    call :dotag "%%b" %*
    call :dotag "%%c"
    call :dotag "%%d"
    call :dotag "%%e"
    call :dotag "%%f"
    call :dotag "%%g"
    call :dotag "%%h"
    call :dotag "%%i"
    call :dotag "%%j"
  )
)
echo.
echo Done.
goto :eof

rem dotag "{id=value}"
:dotag
for /f "tokens=1,2 delims==" %%p in (%1) do (
  set z=0
  if exist tag%%plist.txt (
    call :chktag %%p "%%q"
  ) else (
    rem>tag%%plist.txt
  )
  if !z! == 0 (
    echo %%q>>tag%%plist.txt
    echo %~1
  )
)
goto :eof

rem chktag {id} "{value}"
:chktag
for /f "delims=" %%y in (tag%1%list.txt) do (
  if /i "%%y" == %2 (
    set z=1
    goto :eof
  )
)
goto :eof