windows - batch iterate string med whitespace delimiter, find ord indeholdende substring

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg forstår ikke, hvorfor det ikke virker


@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set contents=sdflkm efsdf sdfkns CRQ239478239
for /f "tokens=1* delims= " \%\%i in ("\%contents\%") do (
  set str=\%\%i
  echo str: !str:~0,3!
    if "!str:~0,3!"=="CRQ" (
      set revision=!str!
    )
)
echo revision: \%revision\%


Jeg vil udtrække ordet i snoren, der begynder med 'CRQ'. Men dette for sløjfe gør kun en iteration og tager de første 3 bogstaver af snoren. Udgangen er kun str: sdf. Det bør kontrollere de første 3 bogstaver af hvert ord i strengen, og hvis de første 3 bogstaver er 'CRQ', skal den sætte revisionsvariablen til ordet indeholdende CRQ. Hvordan gør jeg det her?

Bedste reference


Kommandoen for vil gentage gennem linjer af input. Da din streng kun består af en enkelt linje, får du kun 1 iteration gennem din loop.


Løbet for tokeniserer den enkelte linie i flere tokens. Det passerer det første tegn til \%i, så takket være asterisken i tokens=1* sætter det resten i \%j. Hvis du ændrer dit script lidt, kan du se dette:


set contents=sdflkm efsdf sdfkns CRQ239478239
for /f "tokens=1*" \%\%i in ("\%contents\%") do (
  set str=\%\%i
  echo str: !str:~0,3!
  echo rest: \%\%j
    if "!str:~0,3!"=="CRQ" (
      set revision=!str!
    )
)
echo revision: \%revision\%


hvilke udgange:


str: sdf
rest: efsdf sdfkns CRQ239478239
revisionx:


Min løsning er at oprette en subrutine, som du kan kalde rekursivt på de resterende tokens, indtil du rammer den ønskede du:


@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set contents=sdflkm efsdf sdfkns CRQ239478239
call :ParseTokens \%contents\%
echo revision: \%revision\%

rem Subroutine ParseTokens
:ParseTokens
set ToParse=\%*
for /f "tokens=1*" \%\%i in ("\%ToParse\%") do (
    set str=\%\%i
    if "!str:~0,3!"=="CRQ" (
      set revision=!str!
      exit /b
    ) else (
        call :ParseTokens \%\%j
    )
)
exit /b

Andre referencer 1


Du skal bare ændre din For /F loop til en standard For loop:


@Echo Off
SetLocal EnableDelayedExpansion
Set "Contents=sdflkm efsdf sdfkns CRQ239478239"
Set "Revision="
For \%\%A In (\%Contents\%) Do (Set "Str=\%\%A"
    Echo Str: !Str:~,3!
    If /I "!Str:~,3!"=="CRQ" Set "Revision=!Str!")
Set "Str="
If Defined Revision Echo \%Revision\%
Pause

Andre referencer 2


Skift din for til en enkel og brug \%contents\% uden citater.


for \%\%i in (\%contents\%) do (


Bare en anden variant med et opkald og skiftende argumenter:


@echo off & SETLOCAL
set contents=sdflkm efsdf sdfkns CRQ239478239
Call :Sub \%contents\%
echo revision: \%revision\%
goto :eof
:sub
set str=\%1
echo str: \%str:~0,3\%
if "\%str:~0,3\%"=="CRQ" set revision=\%str\%
If "\%~2" neq "" (shift & goto :sub)