4

I have a batch file that would have something like this:

50-A Description of the item $23

I have a script that extracts whatever is before the $ sign, but I need to extract everything after the $ sign.

Here's the script:

for /f "tokens=1 delims=/" %%a in (test.txt) do (echo %%a >> newfile.txt)

How would I change it?

Compo
  • 36,585
  • 5
  • 27
  • 39
Mark Deven
  • 550
  • 1
  • 9
  • 21

4 Answers4

5

No matter how many $ you have in the line, you can easily get the text after the last one like so:

set "str=Te$ting thi$ $cript for $zero"
set "result=%str:$=" & set "result=%"
echo %result%

Your result in this case would be zero.

Timtech
  • 1,224
  • 2
  • 19
  • 30
  • no, the result in this case would be `ting thi$ $cript for $zero` (everything after the *first* occurrence of `$`) – Stephan May 23 '18 at 06:44
  • @Stephan Yea my bad just realized that, I had forgot part of the code. Fixed now. – Timtech May 23 '18 at 11:40
3

This can be not so trivial task.If you have only one $ symbol you can check the comments.If they are more you can look at the following example (it uses the lastIdexOf subroutine though other approaches are possible - like replacing $ with space and process the result as few strings):

@echo off
::First way - when you have single '$' or you want to strip the substring before the first one
for /f "tokens=1* delims=$" %%a in ("asd$zxc$qwe") do @echo after the first dollar: %%b


::If you have more '$'-es you need something more complex
setlocal enableDelayedExpansion
set "string=asd$zxc$qwe"
call :lastindexof "%string%" $  lastIndex

set /a lastIndex=lastIndex+1
set noDollars=!string:~%lastIndex%!
echo after the last dollar: %noDollars%
endlocal
goto :eof



:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:lastindexof [%1 - string ; %2 - find last index of ; %3 - if defined will store the result in variable with same name]
::http://ss64.org/viewtopic.php?id=1687
@echo off
setlocal enableDelayedExpansion 


set "str=%~1"
set "splitter=%~2"

set LF=^


rem ** Two empty lines are required
echo off
setlocal
for %%L in ("!LF!") DO (
    for /f "delims=" %%R in ("!splitter!") do ( 
        set "var=!str:%%R=%%L!"
    )
)

for /f  delims^=^" %%P in ("!var!") DO ( 
    set "last_part=%%~P"  
)

if "!last_part!" equ ""  if "%~3" NEQ "" (
 echo "not contained" >2 
 endlocal
 set %~3=-1 
 exit
) else (
 echo "not contained" >2 
 endlocal
 echo -1 
)
setlocal DisableDelayedExpansion

set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
set $strLen=for /L %%n in (1 1 2) do if %%n==2 (%\n%
      for /F "tokens=1,2 delims=, " %%1 in ("!argv!") do (%\n%
         set "str=A!%%~2!"%\n%
           set "len=0"%\n%
           for /l %%A in (12,-1,0) do (%\n%
             set /a "len|=1<<%%A"%\n%
             for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"%\n%
           )%\n%
           for %%v in (!len!) do endlocal^&if "%%~b" neq "" (set "%%~1=%%v") else echo %%v%\n%
      ) %\n%
) ELSE setlocal enableDelayedExpansion ^& set argv=,


%$strlen% strlen,str
%$strlen% plen,last_part
%$strlen% slen,splitter

set /a lio=strlen-plen-slen
endlocal & endlocal & endlocal & if "%~3" NEQ "" (
    set "%~3=%lio%"
) else (
    echo %lio%
)
exit /b 0
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

EDIT: Here's another approach:

@echo off

set "string=asd$zxc$qwe"

for %%a in ("%string:$=" "%") do echo set "result=%%~a"
echo %result%
npocmaka
  • 55,367
  • 18
  • 148
  • 187
  • I used your second apporoch when I was using findstr and had a result like `C:\users\Lucas\Test.txt:12:Hello hows it going` (the first is the file, the second the line number, the third the text) – Mark Deven Jan 13 '18 at 15:01
  • Do you know of an easy way to extract the text before a section of a string? I have a variable like `Hello.txt.L.Bat` and I want it to become `Hello.txt'. Note that the strings all end with `.L.bat` – Mark Deven May 10 '18 at 14:31
3

Given that there is only one '$' character for each line, and that you only want the string after the '$' character, you can easily obtain the result with this batch code:

for /f "delims=$ tokens=1*" %%A in (test.txt) do echo %%B

In case you want the result in a log file, you only had to add a redirection:

for /f "delims=$ tokens=1*" %%A in (test.txt) do echo %%B >> result.txt

Using the asterisk in the tokens parameter, you can get the rest of the string after the '$' delimitation.

  • Perfect. There is only one in each line. – Mark Deven Dec 13 '17 at 23:36
  • I'll use `for /f "delims=$ tokens=1*" %%A in (test.txt) do set cash=%%B` – Mark Deven Dec 13 '17 at 23:37
  • You can not use a 'set' command inside the 'for' loop without some previous modifications. If you specify what you want maybe I can modify the code. – Fran Moreno Dec 14 '17 at 01:01
  • @MarkDodsons - see https://stackoverflow.com/questions/9681863/windows-batch-variables-wont-set for using `set` in a `for` loop. – SomethingDark Dec 14 '17 at 02:59
  • I know how to use them. My example works to me without using set. If you want another algorithm, you should be clearer of what you want. Maybe then we can help. Show your code and we'll see. – Fran Moreno Dec 14 '17 at 11:16
  • @FranMoreno I ended up using this: `set "result=%string:*$=%"` to extract the text after the $. Do you know of a way like this that I could get the text before the $? It would be great if I didnt need to make any files, as in keep it in variables. – Mark Deven Dec 29 '17 at 21:19
2

It is possible to use a string substitution to delete everything left to $ and the first dollar sign from line and get just everything after $ into an environment variable if the entire line contains only a single $.

@echo off
if exist test.txt (
    set "Line="
    set /P Line=<test.txt
    if defined Line goto ProcessLine
)
set "Line=50-A Description of the item $23"
:ProcessLine
echo on

set "Value=%Line:*$=%"

@echo off
echo Value after first $ is: %Value%
set "Value="
set "Line="

This batch code reads the first line of file test.txt via input redirection and assigns it to environment variable Line if the file test.txt exists in current directory with the posted example line. Otherwise the environment variable Line is defined with the example text for demonstrating this method.

Line 10 makes the string substitution removing the first $ and everything left to it. Help of command SET output on running set /? in a command prompt window explains this string substitution briefly.

The value of an environment variable is usually referenced with %VariableName% which results in being replaced during preprocessing state of the command line by current value of the referenced environment variable before executing the command line.

A string substitution is specified with colon : after variable name. The asterisk * after the colon informs the Windows command interpreter that everything up to and including first occurrence of searched string specified next up to equal sign = should be replaced by the string after equal sign up to percent sign % indicating end of replace string and additionally the string substitution.

In this case the search string is just the character $ and the replace string is an empty string.

The batch file turns on echo mode temporarily to display that the entire string substitution is done here by Windows command interpreter cmd.exe executing the batch file already during preprocessing the line before executing the command line which is for this example:

set "Value=23"

The next line after turning off echo mode again outputs:

Value after first $ is: 23

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • goto /?
  • if /?
  • set /?

Read also the Microsoft article about Using Command Redirection Operators for an explanation of redirection operator <.

Mofi
  • 46,139
  • 17
  • 80
  • 143