windows - Sådan får du substring fra omvendt til et bestemt tegn ved hjælp af batch script

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg har disse strenge som en liste over filnavne


abc-cdef-ijklm-2018.04.02-vendor1.1.0.0
abc-cdef-pqrs-2018.03.22-writer1.2.0.0
abc-cdef-lmno-2017.03.22-reader22.5.0.5


Jeg skal udpakke disse understrenger fra hver linje, som er fra omvendt efter de sidste 5 bogstaver til bindestreg -.


vendor1
writer1
reader22


Hvordan kan det gøres ved hjælp af enkle batch script.

Bedste reference


Der er flere forskellige måder at løse dette problem på. Dette er en meget enkel en:


@echo off
setlocal

rem Process the strings (from test.txt file)
for /F "delims=" \%\%a in (test.txt) do call :extract "\%\%a"
goto :EOF


:extract

REM ECHO ON

set "string=\%~1"

rem Extract *the last part* after the last dash
set "string=\%string:-=" & set "string=\%"

rem Extract *the first part* before the first dot
set "string=\%string:.=" & rem "\%"

@REM ECHO OFF

echo \%string\%
exit /B


Hvis dette eksempelvis er inputfilen test.txt :


abc-cdef-ijklm-2018.04.02-vendor1.1.0.0
abc-cdef-pqrs-2018.03.22-writer1.2.0.0
abc-cdef-lmno-2017.03.22-reader22.5.0.5


Dette er output:


vendor1
writer1
reader22


Denne metode anvender simpel substring sustitution til at udføre udvinding af de ønskede dele. Det er meget enklere at gennemgå metoden i stedet for forklare det, så du kan aktivere kommandoerne ECHO ON og @ECHO OFF og kontrollere selv hvordan metodeværker.


Hvis du vil have en yderligere forklaring, se dette emne. [59]

Andre referencer 1


Hvis antallet af substrings adskilt af - er konstant fem, kan følgende kode anvendes i batchfil:


@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "\_FileName1=abc-cdef-ijklm-2018.04.02-vendor1.1.0.0"
set "\_FileName2=abc-cdef-pqrs-2018.03.22-writer1.2.0.0"
set "\_FileName3=abc-cdef-lmno-2017.03.22-reader22.5.0.5"

for /F "tokens=1* delims==" \%\%A in ('set \_FileName') do (
    for /F "eol=| tokens=5 delims=-" \%\%C in ("\%\%B") do (
        for /F "eol=| delims=." \%\%D in ("\%\%C") do (
            echo Last part of "\%\%B" is: \%\%D
        )
    )
)
endlocal
pause


Se venligst den yderste FOR -sløjfe, der bruges her, kun for at behandle værdierne for et ubestemt antal miljøvariabler, hvis navn starter med \_FileName.


Den anden FOR -løkke behandler et filnavn som tildelt loop-variabel B i dette tilfælde ved at opdele det i substrings (tokens) med - som afgrænsere som angivet med delims=-.


Af interesse er kun den femte substring. Derfor specificerer tokens=5, at kun den femte substring skal tildeles til specificeret loop variabel A.


Endvidere ændres slutningen af ​​linjestykket fra standard ; til | for at undgå, at et filnavn, der starter med et semikolon, ignoreres fuldstændigt af FOR . Et filnavn kan ikke have en lodret bjælke i navnet.


Så den anden FOR løkke tildeler loop-variabel C strængerne:


vendor1.1.0.0
writer1.2.0.0
reader22.5.0.5


Den tredje FOR -sløjfe bruges til at fjerne alt efter første prik ved
opdeling af denne streng op i substrings ved hjælp af . som afgrænsning med tildeling af netop første substring til specificeret loop variabel D som standard med tokens= mulighed ikke udtrykkeligt angivet. Igen eol=| bruges til at undgå, at strengen fuldstændigt ignoreres af FOR , hvis denne streng begynder med et semikolon.


Så loop variabel D holder på dette eksempel strengen af ​​interesse for videre behandling som bare at printe den til konsol.


Her er en yderligere løsning, der kun bruger strengsubstitutioner i en subrutine LastPart, der er indlejret usædvanligt i midten af ​​batchfilen, hvilket er langsommere, men fungerer også for filnavne med variabelt antal bindestregsubstrider.


@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "\_FileName1=abc-cdef-ijklm-2018.04.02-vendor1.1.0.0"
set "\_FileName2=abc-pqrs-2018.03.22-writer1.2.0.0"
set "\_FileName3=lmno-2017.03.22-reader22.5.0.5"
goto ProcessFileNames


:LastPart
set "FileName=\%~1"
rem Get file name without the last six characters.
set "FileName=\%FileName:~0,-6\%"

rem Remove from file name in a loop everything from beginning to first hyphen
rem character with removing also the hyphen until this is not possible anymore
rem because of file name string not containing anymore a hyphen.

:LastHyphen
set "LastPart=\%FileName:*-=\%"
if not "\%LastPart\%" == "\%FileName\%" set "FileName=\%LastPart\%" & goto LastHyphen

echo Last part of \%1 is: \%LastPart\%

rem Exit subroutine LastPart and return to calling FOR command line.
goto :EOF


:ProcessFileNames
for /F "tokens=1* delims==" \%\%A in ('set \_FileName') do call :LastPart "\%\%B"
endlocal


Og endelig en yderligere variant af ovenstående, hvor antallet af tegn på slutningen af ​​hvert filnavn også kan variere.


@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "\_FileName1=abc-cdef-ijklm-2018.04.02-vendor1.1.0.0"
set "\_FileName2=abc-pqrs-2018.03.22-writer1.2.0.50"
set "\_FileName3=lmno-2017.03.22-reader22.5.10.15"
goto ProcessFileNames


:LastPart
set "FileName=\%~1"

rem Remove from file name in a loop everything from beginning to first hyphen
rem character with removing also the hyphen until this is not possible anymore
rem because of file name string not containing anymore a hyphen.

:LastHyphen
set "LastPart=\%FileName:*-=\%"
if not "\%LastPart\%" == "\%FileName\%" set "FileName=\%LastPart\%" & goto LastHyphen

rem Get string up to first dot from last part of file name.
for /F "eol=| delims=." \%\%I in ("\%LastPart\%") do set "LastPart=\%\%I"

echo Last part of \%1 is: \%LastPart\%

rem Exit subroutine LastPart and return to calling FOR command line.
goto :EOF


:ProcessFileNames
for /F "tokens=1* delims==" \%\%A in ('set \_FileName') do call :LastPart "\%\%B"
endlocal


For at forstå de anvendte kommandoer og hvordan de virker, skal du åbne et kommandopromptvindue, udføre de følgende kommandoer, og læs helt alle hjælpesider, der vises for hver kommando, meget omhyggeligt.



  • call /?

  • echo /?

  • endlocal /?

  • for /?

  • goto /?

  • if /?

  • pause /?

  • rem /?

  • set /?

  • setlocal /?


Andre referencer 2




For at hente det sidste - afgrænsede element kan du bruge en standard for loop som i nedenstående tilgang. Tricket er at erstatte hver - med standard afgrænsning som SPACE og omslutter hver del mellem "" for at beskytte alle de andre forekommende afgrænsere. Så her er den relaterede kode:


@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "\_FILE=\%~1" & rem // (use first command line argument)

rem // Read file line by line (empty lines are ignored):
for /F usebackq^ delims^=^ eol^= \%\%L in ("\%\_FILE\%") do (
    rem // Store line string:
    set "LINE=\%\%L"
    setlocal EnableDelayedExpansion
    rem /* Enclose line string within `""` and replace every `-` by `" "`,
    rem    which results in several space-delimited items within `""`: */
    for \%\%I in ("!LINE:-=" "!") do (
        endlocal
        rem // Store (overwrite) current item with surrounding `""` removed:
        set "ITEM=\%\%~I"
        setlocal EnableDelayedExpansion
    )
    rem // Splif off first `.` and everything after from last item:
    for /F "tokens=1 delims=. eol=." \%\%V in ("!ITEM!") do (
        endlocal
        rem // Return extracted string portion:
        echo(\%\%V
        setlocal EnableDelayedExpansion
    )
    endlocal
)

endlocal
exit /B


Dette script mislykkes, hvis tekstfilen indeholder tegnene *, ?, <, > og ".


I betragtning af at scriptet hedder data-extract.bat, gemmes de strenge, der skal behandles, i en tekstfil med navnet data.txt, og begge er placeret i den nuværende directlry, kør scriptet som dette:


data-extract.bat "data.txt"


For at gemme output i en anden fil (forskellig fra data.txt!), Brug dette:


data-extract.bat "data.txt" > "data\_NEW.txt"

Andre referencer 3


Det er uklart, hvordan du planlægger at få listen over filer, så jeg vil vise nogle få metoder. Dette forudsætter også, at dit filformat vil være nøjagtigt som dine eksempler.


lad os sige, at dine filer har en .PEM udvidelse, så kan vi gøre:


@echo off
for /f "tokens=1-10 delims=-." \%\%a in ('dir /b *.PEM') do echo \%\%g


Hvis du har en liste over filnavne i en fil, lad os kalde det file.txt, hvor indholdet er som:


abc-cdef-ijklm-2018.04.02-vendor1.1.0.0
abc-cdef-pqrs-2018.03.22-writer1.2.0.0
abc-cdef-lmno-2017.03.22-reader22.5.0.5


Så skal denne gøre:


@echo off
for /f "tokens=1-10 delims=-." \%\%a in ('type file.txt') do echo \%\%g


Men hvis du gør det klart, hvordan du får adgang til filnavne, så kan jeg ændre mit svar.