Пакетный файл для извлечения текста из файла - PullRequest
1 голос
/ 25 сентября 2019

У меня есть файл журнала, из которого я пытаюсь извлечь определенные строки.Когда я обрезаю файл на несколько строк выше и ниже, я могу его получить.Тем не менее, есть несколько примеров того, что я пытаюсь найти, предотвращая использование файла FULL.

Ниже приведен код, который я пробовал ...

 for /f "tokens=1* delims=[]" %%a in ('find /n "    <Line Text="***********TEST1  TEST  TEST************" />" ^< TEST.LOG') do (set H=%%a
 )

 for /f "tokens=1* delims=[]" %%a in ('find /n "</Report>" ^< TEST.LOG') do (
 set T=%%a
 )

 for /f "tokens=1* delims=[]" %%a in ('find /n /v "" ^< TEST.LOG') do (
 if %%a GEQ !H! if %%a LEQ !T! echo.%%b
 )>> newfile.txt

Я надеюсь получитьследующее:

 <Line Text="***********TEST1  TEST  TEST************" />
 ~ALL LINES IN BETWEEN~
 </Report>

Ответы [ 3 ]

2 голосов
/ 25 сентября 2019

Обновлено:

Вы хотите найти <Line Text="***********TEST1 TEST TEST************" />, затем распечатать его и любую строку, пока не встретите First </Report>, затем найдите следующий <Line Text="***********TEST1 TEST TEST************" /> и распечатайте егои каждую следующую строку до следующей </Report> за каждый раз, когда это происходит повсюду?

- Бен Персоник 1 час назад

ИЛИ вы просто хотите взять усначала <Line Text="***********TEST1 TEST TEST************" /> до первого </Report>?

- Бен Персоник 1 час назад

Найдите <Line Text="***********TEST1 TEST TEST************" />, затем напечатайте его и любую строку до первого </Report>, затем найдите следующий <Line Text="***********TEST1 TEST TEST************" /> и напечатайте его и каждую следующую строку до следующей </Report> для каждого раза, когда это происходит.Я чувствую, что должна быть ТОЛЬКО 1 последовательность, однако иногда такая ситуация вполне может быть возможной.Спасибо, что задали очень серьезный вопрос!

- T-Diddy 1 час назад

Хорошо, тогда все должно работать так, как вы ожидаете, однако , еслиесть много неожиданных символов, возможно, имеет смысл изменить порядок вывода строк , чтобы использовать SET вместо эха.

@(setlocal
  ECHO OFF
  SET "_LogFile=C:\Admin\TestLog.log"
  SET "_ResultFile=C:\Admin\TestLog.txt"
  SET "_MatchString_Begin=<Line Text="***********AAAAA BBBB CCCC************" />"
  SET "_MatchString_End=</Report>"
  SET "_Line#_Begin="
)

CALL :Main

( ENDLOCAL
  EXIT/B
)
:Main
  IF EXIST "%_ResultFile%" (
    DEL /F /Q "%_ResultFile%"
  )
  ECHO.&ECHO.== Processing ==&ECHO.
  FOR /F "Delims=[]" %%# IN ('
    Find /N "%_MatchString_Begin:"=""%" "%_LogFile%" ^| FIND "["
  ') DO (
    ECHO. Found Match On Line %%#
    SET /A "_Line#_Begin=%%#-1"
    CALL :Output
  )
  ECHO.&ECHO.== Completed ==&ECHO.&ECHO.Results to Screen will Start in 5 Seconds:
  timeout 5
  Type "%_ResultFile%"
GOTO :EOF

:Output
  FOR /F "SKIP=%_Line#_Begin% Tokens=* usebackq" %%_ IN (
    "%_LogFile%"
  ) DO (
    ECHO(%%_
    ECHO("%%_" | FIND /I "%_MatchString_End%" >NUL&&(
      GOTO :EOF
    )
  )>>"%_ResultFile%"
GOTO :EOF

Только в исходном ответе отображается первый найденный контент на основена этот Комментарий:

Это прекрасно работает с моим "обрезанным" файлом.Однако в ОРИГИНАЛЕ единственная уникальная строка, которую я имею, - <Line Text="***********AAAAA BBBB CCCC************" />.Кажется, я не могу использовать полную строку, так как моя партия только что вышла, но я могу ввести "***********AAAAA BBBB CCCC************" и не выгнать мою партию, однако существует в другом месте.Таким образом, требуются другие параметры, так как они уникальны в файле.и я хочу следующее: по порядку.В противном случае это «</Report>» существует выше в другом разделе, который я не хочу и считаю, вызывает проблему.- T-Diddy 3 минуты назад

Хорошо, я так и думал.

Попробуйте:

@(setlocal
  ECHO OFF
  SET "_LogFile=C:\Admin\TestLog.log"
  SET "_MatchString_Begin=<Line Text="***********AAAAA BBBB CCCC************" />"
  SET "_MatchString_End=</Report>"
  SET "_Line#_Begin="
  SET "_Line#_End="
)
REM SET
FOR /F "Delims=[]" %%# IN ('
  Find /N "%_MatchString_Begin:"=""%" "%_LogFile%" ^| FIND "["
') DO (
  IF NOT DEFINED _Line#_Begin (
    SET /A "_Line#_Begin=%%#-1"
    ECHO.SET /A "_Line#_Begin=%%#-1"
  )
)
FOR /F "SKIP=%_Line#_Begin% Tokens=* usebackq" %%_ IN (
  "%_LogFile%"
) DO (
  IF NOT DEFINED _Line#_End (
    ECHO(%%_
    ECHO("%%_" | FIND /I "%_MatchString_End%" &&(
      SET "_Line#_End=1"
    )
  )
)
PAUSE
2 голосов
/ 25 сентября 2019

Командный процессор Windows, предназначенный для выполнения команд и исполняемых файлов, а не для обработки текстовых файлов, безусловно, является худшим выбором для фильтрации TEST.LOG.По причинам, полностью прочитанным в моем ответе на Как читать и печатать содержимое текстового файла построчно? Детально описанный там код пакетного файла использовался в качестве шаблона для кода пакетного файла ниже:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if not exist "Test.log" goto EndBatch
set "OutputLines="

(for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "Test.log"') do (
    set "Line=%%I"
    setlocal EnableDelayedExpansion
    if defined OutputLines (
        echo(!Line:*:=!
        if not "!Line:</Report>=!" == "!Line!" (
            endlocal & set "OutputLines="
        ) else endlocal
    ) else if not "!Line:<Line Text=!" == "!Line!" (
        echo(!Line:*:=!
        endlocal & set "OutputLines=1"
    ) else endlocal
))>"newfile.txt"

if exist "newfile.txt" for %%I in ("newfile.txt") do if %%~zI == 0 del "newfile.txt"

:EndBatch
endlocal

Этот пакетный файл записывает все строки из строки, содержащей без учета регистра строку <Line Text, в строку, содержащую без учета регистра строку </Report> или конец файла из Test.log в файл newfile.txt.

Примечание: Строка поиска между !Line: и = не может содержать знак равенства, поскольку знак равенства интерпретируется командным процессором Windows как разделитель между строкой поиска, здесь </Report>и <Line Text, и строка замены, здесь дважды пустая строка.А звездочка * в начале строки поиска интерпретируется командным процессором Windows как порядок замены всего от начала строки до первого появления найденной строки при выполнении подстановки строки, а не в качестве символа для поиска в строке.Но это не имеет значения для этого варианта использования.

Если две строки, отмечающие начало и конец извлекаемого блока, являются фиксированными и не содержат какой-либо переменной части, сравнение двух строк может быть выполнено без подстановки строки, что делаетМожно также сравнивать строки, содержащие знак равенства.

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if not exist "Test.log" goto EndBatch

set "BlockBegin= <Line Text="***********TEST1  TEST  TEST************" />"
set "BlockEnd= </Report>"
set "OutputLines="

(for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "Test.log"') do (
    set "Line=%%I"
    setlocal EnableDelayedExpansion
    if defined OutputLines (
        echo(!Line:*:=!
        if "!Line:*:=!" == "!BlockEnd!" (
            endlocal & set "OutputLines="
        ) else endlocal
    ) else if "!Line:*:=!" == "!BlockBegin!" (
        echo(!Line:*:=!
        endlocal & set "OutputLines=1"
    ) else endlocal
))>"newfile.txt"

if exist "newfile.txt" for %%I in ("newfile.txt") do if %%~zI == 0 del "newfile.txt"

:EndBatch
endlocal

Этот вариант сравнивает каждую строку с учетом регистра со строками, присвоенными переменным среды BlockBegin и BlockEnd, чтобы определить, с какой строки начинатьи в какой строке останавливать вывод строк.

Для понимания используемых команд и их работы откройте окно командной строки, выполните там следующие команды и полностью прочитайте все страницы справки, отображаемые для каждой команды.очень осторожно.

  • del /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • goto /?
  • if /?
  • set /?
  • setlocal /?

Смотри также:

0 голосов
/ 25 сентября 2019

Вы можете попробовать с этим кодом:

@echo off
Title Extract Data between two tags
Set "InputFile=InputFile.txt"
Set From_Start="<Line"
Set To_End="</Report>"
Set "OutputFile=OutputFile.txt"
Call :ExtractData %InputFile% %From_Start% %To_End%
Call :ExtractData %InputFile% %From_Start% %To_End%>%OutputFile%
If Exist %OutputFile% Start "" %OutputFile%
Exit
::'*************************************************************
:ExtractData <InputFile> <From_Start> <To_End>
(
echo Set fso = CreateObject^("Scripting.FileSystemObject"^)
echo Set f=fso.opentextfile^("%~1",1^)
echo Data = f.ReadAll
echo Data = Extract(Data,"(%~2.*\r\n)([\w\W]*)(\r\n)(%~3)"^)
echo WScript.StdOut.WriteLine Data
echo '************************************************
echo Function Extract(Data,Pattern^)
echo    Dim oRE,oMatches,Match,Line
echo    set oRE = New RegExp
echo    oRE.IgnoreCase = True
echo    oRE.Global = True
echo    oRE.Pattern = Pattern
echo    set Matches = oRE.Execute(Data^)
echo    If Matches.Count ^> 0 Then Data = Matches^(0^).SubMatches^(1^)
echo    Extract = Data
echo End Function
echo '************************************************
)>"%tmp%\%~n0.vbs"
cscript //nologo "%tmp%\%~n0.vbs"
If Exist "%tmp%\%~n0.vbs" Del "%tmp%\%~n0.vbs"
exit /b
::****************************************************
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...