Como extrair uma parte de uma linha que está entre duas strings específicas por meio de um script em lote

Como extrair uma parte de uma linha que está entre duas strings específicas por meio de um script em lote

Estou tentando extrair strings que estão entre testid=e ].

Arquivo de texto de entrada

SEVERE  TEST 11/18/2019 8:00:41 AM  Could not find INPUT with [testid=2345]
SEVERE  TEST 11/18/2019 5:02:11 AM  Could not find INPUT with [testid=12345678]

Resultado esperado

2345
12345678

Responder1

Tente isso,

@echo off
for /F "tokens=* USEBACKQ" %%F in (`findstr /I /C:"8:00:41" text.txt`) do (
set string=%%F
)
set string=%string:~68%
set string=%string:~,-1%
echo %string%
for /F "tokens=* USEBACKQ" %%F in (`findstr /I /C:"5:02:11" text.txt`) do (
set string2=%%F
)
set string2=%string2:~68%
set string2=%string2:~,-1%
echo %string2%
pause

A saída que você obterá é,

2345
12345678
Press any key to continue...

Se você quiser se livrar dessa última parte, substitua o

pause

no final, com um

pause > nul

e a saída que você obterá é

2345
12345678

Responder2

Você pode fazer isso com um arquivo em lote usando Regex em vbscript:

@echo off
Title Extract Data between string and char from a text file using RegExp
Set "InputFile=Test.txt"
Set "OutputFile=OutputFile.txt"
Call :ExtractData "%InputFile%" "%OutputFile%"
If Exist %OutputFile% Start "" %OutputFile%
Exit
::-----------------------------------------------------------------------------------
:ExtractData <InputFile> <OutputFile>
(
    echo WScript.StdOut.WriteLine Extract("%~1"^)
    echo Function Extract(Data^)
    echo Dim strPattern,strResult,oRegExp,Match,colMatches 
    echo Data = WScript.StdIn.ReadAll
    echo strPattern = "\[testid=(.+)\]"
    echo Set oRegExp = New RegExp
    echo oRegExp.Global = True
    echo oRegExp.Multiline = True
    echo oRegExp.IgnoreCase = True 
    echo oRegExp.Pattern = strPattern
    echo set colMatches = oRegExp.Execute(Data^)
    echo For Each Match in colMatches
    echo    strResult = strResult ^& Match.SubMatches(0^) ^& vbcrlf
    echo Next
    echo Extract = strResult
    echo End Function
)>"%tmp%\%~n0.vbs"
cscript //nologo "%tmp%\%~n0.vbs" < "%~1" > "%~2"
If Exist "%tmp%\%~n0.vbs" Del "%tmp%\%~n0.vbs"
Exit /B
::----------------------------------------------------------------------------------

O arquivo de saída é assim:

2345
12345678

Responder3

Este arquivo em lote extrai o texto entre (o primeiro) testid= (se houver) em cada linha e o (primeiro) subsequente ](se houver), independentemente de onde eles aparecem na linha, com uma exceção que consegui identificar (veja parte inferior da resposta):

@echo off
setlocal enabledelayedexpansion
for /f "tokens=*" %%L in (input.txt) do (
    set line=%%L
    set right1=!line:*testid=!
    if not !line! == !right1! (
        set left=!right1:~0,1!
        if "!left!" == "=" (
            set right2=!right1:~1!
            for /f "tokens=1 delims=]" %%W in ("!right2!") do (
                if not %%W == !right2! (
                    echo.%%W
                )
            )
        )
    )
)
  • setlocal enabledelayedexpansionpermite trabalhar de forma inteligente com variáveis ​​em loops.
  • for /f "tokens=*" %%L in (input.txt)input.txtuma linha por vez e coloca cada linha na variável de índice %%L.
  • set line=%%Lcopia o texto em uma variável regular, que é mais fácil de manipular.
  • set right1=!line:*testid=! usa a sintaxe para fazer uma substituição de string em uma expansão de variável (espaços são adicionados para maior clareza).% var : str1 = str2 %

    • Usando !em vez de %devido à expansão atrasada.
    • varé line, obviamente.
    • str1é *testid. O  *é um curinga (símbolo de correspondência de padrão), portanto, corresponde a tudo até a primeira ocorrência de testidin  line. Observe que, embora gostaríamosstr1ser *testid=, mas, infelizmente, é impossível parastr1conter =, porque =é o delimitador entrestr1str2.
    • str2é nulo.

    Portanto, isso substitui tudo até a primeira ocorrência de testidin  linepor null e retorna tudo depois de testid.

  • Se a linha não contiver testid, o valor acima retornará o valor inteiro line, inalterado. Então, se linefor igual right1, não havia nenhum testidna linha. Se forem diferentes, prossiga para a análise desta linha.
  • set left=!right1:~0,1!extrai o primeiro caractere (mais à esquerda) de right1.
  • if "!left!" == "=", o primeiro caractere depois testidé =, então encontramos testid=e queremos continuar analisando a linha.
  • set right2=!right1:~1!define right2como todos, right1 exceto o primeiro caractere; ou seja, depois do  =.
  • for /f "tokens=1 delims=]" %%W in ("!right2!")se separa right2no primeiro ], colocando o texto antes ]em %%W.
  • Se %%W == !right2!, não havia nenhum ]na fila.
  • Se encontrarmos testid=e ], então %%Wo texto está entre eles. Você provavelmente deveria atribuí-lo a uma variável regular.

Divulgação: dada a linha

[testid=a] and [testid=b]

este arquivo em lote encontrará aapenas; não encontrará b. Dada a linha

[testid<c] and [testid=d]

o arquivo em lote não encontrará nada; o primeiro testidjoga fora.

informação relacionada