I would have been helpful had you included a link to something that explains the technique you are attempting to use. Thankfully, I am familiar with the technique.
You are attempting to use variable expansion find/replace to inject a comment into a string so that you can extract the beginning of the string, up until some substring. I am more familiar with using REM
, but your use of a :
label as a pseudo comment should work as well.
I'll show a quick example of how this can work. I have ECHO ON
at strategic lines so that you can see how the substitution works. This requires that I use REM
instead of :
because labels are not ECHOed.
@echo off
setlocal
set "var=String Before<split here>String After"
echo on
set "Before=%var:<split here>="&rem %
@set before
set "After=%var:*<split here>=%"
@set after
--OUTPUT--
C:\test>set "Before=String Before" & rem String After
Before=String Before
C:\test>set "After=String After"
After=String After
The extra spaces around the &
are an artifact of how cmd.exe echoes the line, they are not really introduced by the find/replace. But you should be able to see how the technique works.
I don't understand why you have included commas and quotes in your search string - they are not there in your starting string, so nothing will get replaced.
It is important that you use quotes when you save the initial value of %~1
so as to protect against poison characters.
Finally, it is also critical to have quotes in your subsequent assignments. The first quote is before the variable name, and the closing quote is injected by the replace term, just prior to the &:
.
Because you are using :
instead of REM
, there is no need to introduce a space after the :
.
Here is working code. Note that I eliminated the need for an extra var
variable by using Back
for the temporary values until I am ready to get the final Back value.
@echo off
setlocal
call :extract "Hello there this is a block: [C]Inside of Block[/C] Did you like it?"
echo Front = "%Front%"
echo Inside = "%Inside%"
echo Back = "%Back%"
exit /b
:extract
set "Back=%~1"
set "Front=%Back:[C]="&:%
set "Back=%Back:*[C]=%"
set "Inside=%Back:[/C]="&:%
set "Back=%Back:*[/C]=%"
exit /b
-- OUTPUT --
Front = "Hello there this is a block: "
Inside = "Inside of Block"
Back = " Did you like it?"
Note my use of quotes in the output - they are not in the actual stored values. Rather they are introduced by the ECHO command to show the existence of the trailing/leading space, and also they would protect against poison characters.
The above technique has a few restrictions:
- The
%~1
value should not contain any quotes, else you run the risk of poison characters corrupting the result
- The
%~1
value cannot contain newline (0x0A) or carriage return (0x0D).
- The substrings that you are replacing (
[C]
and [/C]
in your case) must not begin with ~
, *
, or %
.
- The substrings that you are replacing must not contain
=
anywhere within them
Here is a totally unrelated JREPL.BAT solution
If you like working with regular expressions, then you could use my JREPL.BAT - a pure script utility (hybrid JScript/batch) that runs natively on any Windows machine from XP onward, no need for any 3rd party .exe file.
The JREPL solution will be a bit slower than pure batch for this application, but it has two big advantages:
- The logic is more straight forward, as long as you understand regular expressions
- There are no character limits.
%~1
still cannot contain carriage return or linefeed. But a variable may, and JREPL will work just fine with those characters.
If you only need to extract a single value, then the solution is really simple - JREPL has the ability to store the result in an environment variable. The code below will capture the value inside your block:
@echo off
setlocal
call :extract "Hello there this is a block: [C]Inside of Block[/C] Did you like it?"
echo Inside = "%Inside%"
exit /b
:extract
set "Inside=%~1"
call jrepl "\[C](.*)\[/C]" "$txt=$1" /s Inside /jmatchq /rtn Inside
exit /b
-- OUTPUT --
Inside = "Inside of Block"
But you want to capture 3 values. You could make three separate JREPL calls, but that would be inefficient. In the code below I insert VariableName=
and newlines in the appropriate places, and let FOR /F
iterate and store the three results.
@echo off
setlocal
call :extract "Hello there this is a block: [C]Inside of Block[/C] Did you like it?"
echo Front = "%Front%"
echo Inside = "%Inside%"
echo Back = "%Back%"
exit /b
:extract
set "Front=%~1"
for /f "delims=" %%A in (
'jrepl "^|\[C]|\[/C]" "Front=|\nInside=|\nBack=" /s Front /t "|" /xseq'
) do set "%%A"
exit /b
-- OUTPUT --
Front = "Hello there this is a block: "
Inside = "Inside of Block"
Back = " Did you like it?"
Extensive help is built into the JREPL utility.
JREPL /?
will list all the help.
JREPL /?options
will briefly summarize all available options
JREPL /?/T
will describe the Translate option that I used. You can do the same for /?/XSEQ
and /?/S
You will likely find many uses for JREPL once have it in your arsenal of tools. JREPL really shines when it comes to manipulating text files - it is much faster and more powerful than any pure batch solution.
1It's unclear to me what you intend with your substitutions, but if using
poisenous
characters like<>|&
you'll have to enclose the whole set var=value pairs in double quotes ->Set "Front=%var:,"[C]"=&:%"
(don't know what the inner double quotes are meant for). – LotPings – 2018-10-02T18:19:26.977Oh I think the quotes are mistakes. I’ll check. – Mark Deven – 2018-10-02T18:22:32.437
If you have delayed expansion enabled then
%
needs to be replaced by!
– DavidPostill – 2018-10-02T20:06:16.410@Worthwelle: Please look and see what you overlooked. – Scott – 2018-10-02T20:07:14.940
Mark Dodsons: Thanks for showing us the code you’ve written, but please don’t just throw code at us and say “it is not working.” What *is* it doing? What have you learned from your debugging? (You have tried debugging this on your own, right?) Is
var
getting the desired value from%~1
? What values are the other assignments yielding? (Theecho
statement is your friend.) For that matter, what values are you expecting to get from the assignments? I don’t understand them either; please explain the logic of your code. … (Cont’d) – Scott – 2018-10-02T20:07:18.727Not when it’s a call – Mark Deven – 2018-10-02T20:07:20.430
(Cont’d) … Please do not respond in comments; [edit] your question to make it clearer and more complete. – Scott – 2018-10-02T20:07:23.460
Oh, I almost forgot to ask: why aren’t you expecting (wanting) to get
Hello there
in “Front”? – Scott – 2018-10-02T20:11:01.440Guys some people don’t have unlimited time. I’ll figure it out on my own if it takes this much work. I’m trying to avoid all the debugging if someone with experience can easily see something wrong with my code, such as the quotes which probably is the problem. That’s part of what this site is all about. If that isn’t it then yes I will add debug info and more but with two jobs, high school, college and helping my single parent I can’t spend all this time on this. I haven’t had a minute at my computer to test anything yet (I’m mobile) but once I have I’ll get back to you. – Mark Deven – 2018-10-02T20:12:24.347
If this website can’t handle that then it isn’t something that can help my most of the time. Forgive me if I’m seeming rude but the attitude that comes on most of these has an extremely judgmental tone. – Mark Deven – 2018-10-02T20:14:00.790
Most coders I work with refuse to use these sites for that exact reason. This should be for helping the community, not pleasing the select few with the highest rep. – Mark Deven – 2018-10-02T20:18:25.573
However it was a typo with the hello there text – Mark Deven – 2018-10-02T20:19:37.423