0

我正在处理非常大的 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...

输出的格式并不重要。

我将不胜感激任何建议和建议。

亲切的问候,维克多·O。

4

2 回答 2

2

选项1

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

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

编辑- 我的原始代码根本不支持=该值。我通过在变量名中添加一个额外的 SOH 字符来减少这种限制,并更改了用于解析值的分隔符。现在=,只要在=. 如果值在 之后有差异,=则将仅保留一个值。

请务必在顶部附近修复 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 限制,我使用文件而不是命令行搜索字符串。命令行搜索字符串不能匹配许多 > 十进制 128 的字符。此外,文字反斜杠的转义规则在命令行上也不一致。请参阅Windows FINDSTR 命令有哪些未记录的功能和限制?了解更多信息。

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
)
于 2012-07-22T04:17:50.583 回答
1

试试这个批处理文件。添加日志文件名作为参数。例如:

LISTTAG.BAT SOH.LOG

它将显示所有标签 ID 及其唯一值。例如:

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

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

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

需要注意的一件事是,代码只会处理从第 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
于 2012-07-20T18:50:04.993 回答