B S
B S

Reputation: 29

In batch script, split only last string match in a variable

In a batch script, I need to split only the last string match in a variable in a loop until I no longer have the string match.

Input=Level1/Level2/Level3/Level4/LevelN

(where N can be any number)
Output:

Level1/LeveL2/Level3/Level4
Level1/LeveL2/Level3
Level1/Level2
Level1

I have tried the usual "for /f "delims=/"" loops, but they only output each split of the input variable on an individual line. Besides, the value of "N" can vary. So I can't set the number of tokens to a certain value.

Please help.

Upvotes: 0

Views: 940

Answers (4)

lit
lit

Reputation: 16236

This is easily done with a regex in PowerShell. Since the regex is greedy be default, it will get everything up to the last SOLIDUS and store it in the $1 group.

SET "S=Level1/Level2/Level3/Level4/LevelN"

FOR /F "delims=" %%a IN ('powershell -NoL -NoP "'%S%' -replace '(.*/).*', '$1'"') DO (
    SET "RESULT=%%a"
)

ECHO RESULT is set to %RESULT%

Revision:

This outputs all groups and not just the last one.

SET "S=Level1/Level2/Level3/Level4/LevelN"

FOR /F "delims=" %%a IN ('powershell -NoL -NoP -Command ^
    "$a = '%S%'.Split('/'); " ^
    "for ($i = $a.Count - 2; $i -ge 0; $i--) { $a[0..$i] -join '/' }"') DO (
    ECHO %%a
)

Upvotes: 0

Aacini
Aacini

Reputation: 67216

A more classical approach, just for fun...

@echo off
setlocal EnableDelayedExpansion

set "Input=Level1/Level2/Level3/Level4/LevelN"

rem Split the string, join it again and store partial results
set "aux="
set "n=0"
for %%a in ("%Input:/=" "%") do (
   set "aux=!aux!/%%~a"
   set /A n+=1
   set "out[!n!]=!aux:~1!"
)

rem Show results in reverse order
set /A n-=1
for /L %%i in (%n%,-1,1) do echo !out[%%i]!

Upvotes: 0

aschipfl
aschipfl

Reputation: 34909

Here is a nice recursive approach that makes use of the ~ modifiers, assuming that the input string is provided as a quoted ("") command line argument, which does not begin with /, does not contain two consecutive // and none of the characters ", \, *, ?, <, >:

@echo off
rem // Store argument in variable:
set "INPUT=%~1"
if not defined INPUT exit /B
rem /* Precede with `\` and replace each `/` by `\`, so the resulting string appears to
rem    be an absolute path, which can be split by `~` modifiers of `for` variables;
rem    the inner `for` loop resolves the split path and removes any `\.` suffix: */
for %%I in ("\%INPUT:/=\%") do for %%J in ("%%~pI.") do set "REST=%%~pnxJ"
rem // Revert replacement of every `/` by `\` and remove the previously preceded `\`:
set "REST=%REST:\=/%"
set "REST=%REST:*/=%"
rem // If there is a string left, output it and call this script recursively:
if defined REST (
    setlocal EnableDelayedExpansion
    echo(!REST!
    endlocal
    call "%~f0" "%REST%"
)

Upvotes: 2

Aacini
Aacini

Reputation: 67216

This site don't works that way. You must post some code and explain the problems you have with it. In this way you can understand the changes made to your own code. If you request us for code, any code, then you could receive one ("any code") like this:

@echo off
setlocal EnableDelayedExpansion

set "Input=Level1/Level2/Level3/Level4/LevelN"

:loop
   set "Output="
   set "part=%Input:/=" & set "Output=!Output!/!part!" & set "part=%"
   set "Input=%Output:~1%"
   if "%Input%" equ "~1" goto exitLoop
   echo "%Input%"
goto loop

:exitLoop

Upvotes: 4

Related Questions