Suppose I have a value such as "Abc_123" that's stored in a variable in a batch (cmd) file. I want to end up with a variable that contains only "123". Is there any built-in way to do this?

I'm not terribly picky about the method, or performance, as long as it's built in to a typical Windows (Vista/2008) system.


6 Answers 6


Use the substring syntax:

C:\Users\John>set string=Abc_123

C:\Users\John>echo %string%

C:\Users\John>echo %string:~4,3%
  • 6
    You can see the full syntax with help set as mentioned in What is the best way to do a substring in a batch file? on StackOverflow.
    – User5910
    Oct 25, 2016 at 22:49
  • 5
    If I needed that 4 and 3 to be variable inputs, how would I do that? %string:~%start%,%len%%
    – ToMakPo
    Nov 18, 2017 at 19:06
  • 2
    never mind. I found the answer. ss64.com/nt/syntax-substring.html
    – ToMakPo
    Nov 18, 2017 at 19:27
  • 3
    To summarize the link from @MakPo: use CALL, like CALL SET _substring=%%_donor:~%_startchar%,%_length%%%
    – bugybunny
    Feb 4, 2019 at 13:10
  • @ToMakPo The CALL solution is essential. i struggled til i found that, thx to you! Should be part of an answer.
    – johny why
    Nov 20, 2021 at 17:44

If you just want everything after the underscore (and do not necessarily know the length of the string or where the underscore is, but can rely on there being only one underscore), try:

for /f "tokens=2 delims=_" %%a in ("%STRING%") do (

Basically, your string will be split into tokens using the underscore as a delimiter (delims=_). Only the second one (tokens=2) will be passed (as variable %%a) to the for loop. The loop will only run once since you are dealing with a single string in this case.

If you want to save the stuff both before and after the underscore, try:

for /f "tokens=1,2 delims=_" %%a in ("%STRING%") do (

Note that %%a is the variable for the first token of the split; %%b is the variable for the second token of the split.

set var1=Abc_123
set var2=%var1:*_=%
echo %var2%
  • 5
    What does this do specifically? Oct 29, 2019 at 17:09
  • Oh, if you were asking how this code works: it removes everything before the number, preceded by an underscore.
    – Zimba
    Nov 23, 2019 at 13:31
  • @Zimba is there a way to simply extend this to "last _"? Also where can I find this in any documentation?
    – TWiStErRob
    Jan 25, 2020 at 0:40
  • 1
    @TWiStErRob: I see. If you don't know how many _ there are, then loop to the last one, then set var
    – Zimba
    Jan 29, 2020 at 16:24
  • 2
    You mean to be left with Abc_, like a head function?
    – Zimba
    Jun 25, 2021 at 17:24

This will extract last token from string with any tokens number and any type of delimiters. In this example ECHO will show "i". Although it requires a loop function, it's very fast.

@echo off
set "Var=a_b_c_d_e_f_g_h_i"
call :LoopLastToken "%Var%"
echo "%Var%"

    set "Var=%~1"
    if not "%Var:*_=%"=="%~1" (
    call :LoopLastToken "%Var:*_=%")
exit /b

If you find that the batch language isn't powerful enough to do what you want - and it likely won't take you too long to get to that point - you can use the Windows PowerShell. This isn't installed by default on all versions of Windows, but you can download it free of charge.

If you don't like the PowerShell language, there's Perl. You'll have to install that on all systems though. There are others too.

  • 3
    The question is not asking about Powershell or Perl
    – Zimba
    Oct 29, 2019 at 13:31
  • 2
    Powershell requires (much) more resources (RAM) than cmd so if all you need is something quick and simple, it makes more sense to use cmd. CMD uses native Win32 calls and Powershell uses the .Net framework. Powershell takes longer to load, and can consume a lot more RAM than CMD. "I monitored a Powershell session executing Get-ChildItem. It grew to 2.5GB (all of it private memory) after a few minutes and was no way nearly finished. CMD “dir /o-d” with a small scrollback buffer finished in about 2 minutes, and never took more than 300MB of memory." qr.ae/pGmwoe
    – johny why
    Nov 20, 2021 at 17:52

If you need a batch substring implementation which is able to accept variables for start-of-string and length of string then I would suggest the following answer:

@echo off
set sLongString=Abc_123
set StartPos=4
set Len=3
call :Substring %sLongString% %StartPos% %Len% sSubStrResult
echo %sSubStrResult%

Output: 123


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .