joining lines while adding white-spaces to select strings in CMD is not working - string

my test string is:
this is a sentence.
google.com
here is another sentence.
microsoft.com
this sentence has no period
my code is:
#echo off
setlocal EnableDelayedExpansion
set row=
#((For /F "EOL=|Delims=" %%# In ('^""%__AppDir__%find.exe" "."^<"%UserProfile%\i.txt"^"')Do #Set /P "=%%# "<NUL)&Echo()>"%UserProfile%\o.txt"
echo %row% >%userprofile%\o.txt
echo %row%
C:\Users\qwerp>joint3
ECHO is off.
i was expecting to get:
google.com microsoft.com
instead i got:
ECHO is off.
what am i doing wrong?

Given your example file content change and the stated intention, this may be sufficient for your needs, simply changing find.exe to findstr.exe, (with appropriate options):
#((For /F "EOL=|Delims=" %%# In ('^""%__AppDir__%findstr.exe" "\." "%UserProfile%\i.txt"^|"%__AppDir__%findstr.exe" "[^\.]$"^"')Do #Set /P "=%%# "<NUL)&Echo()>"%UserProfile%\o.txt"

Related

Cannot set environmental variable inside a loop in a batch script

I have a batch script that works great and it does the following:
download EDI files from sftp server
generate a dynamic ftp scripts based on the filenames that were downloaded
uploads the file to an internal ftp server via FTP script
I need to modify the batch file to look at the content as some data coming in maybe missing a 0. I do have the logic on how to do this, however, I cannot add the logic to the loop I have as variables do not work.
Below is loop where I want to add the part to correct missing leading zero (that would be in position 4):
for /F "tokens=*" %%A in (c:\scripts\permitsin.txt) do (
echo put %%A /qsys.lib/MAEPFTDTA.lib/PERMITIN.file/%%A >> c:\scripts\ftp-to-scoopsoft.ftp1
)
What I need to do is add an environment variable which will be the content of the file and below is the sample code:
set /p string =< %%A
echo Value for string is set to %string%
echo %string:~9,1% | find "ECHO is on." > nul
if not errorlevel 1 goto Found0
echo no space found
goto End
:Found0
echo found space
echo below is what the correct number needs to be
echo %string:~0,3%0%string:~3% > %%A
:End
I need this to work in batch file as security requirements does not allow PowerShell on the servers.
for /F "tokens=*" %%A in (c:\scripts\permitsin.txt) do (
for /F "delims=" %%S in (%%A) do (
setlocal enabledelayedexpansion
set "string=%%S"
if "!string:~9,1!"==" " echo !string:~0,3!0!string:~3!> %%A
endlocal
)
echo put %%A /qsys.lib/MAEPFTDTA.lib/PERMITIN.file/%%A >> c:\scripts\ftp-to-scoopsoft.ftp1
)
should do what you appear to need. Test on sample data first, of course.
Here's the how : Stephan's DELAYEDEXPANSION link
And it saves a lot of work if you tell us what you want to do rather than how you want to do it.

Batch Manipulating String by Input Variable Using "=&rem."

Using Server 2016 here with simple batch-file programming (for now).
I have what I think is an easy problem, just that I am not seeing a workable solution in front of me right now. I'm going to limit my request right down to a testing scenario to keep it simple. What I am trying to do is trim a string from the right until it hits the current year in the format "_%year%-" where the year does come from a variable elsewhere, but is set static in my example. Where I am running into issues is referring to a variable from within the code I have.
This is a working example NOT using a variable on the rem line, and gives the desired output of "Machined_Cam-2286:"
#ECHO OFF
SETLOCAL DisableDelayedExpansion
set "testString=Machined_Cam-2286_2017-09-08.slddrw - SOLIDWORKS"
set "systemYear=2017"
set "yearModified=_%systemYear%-"
echo "%testString%" | find "%yearModified%" >NUL || goto :EOF
set testString=%testString:_2017-=&rem.%
echo %testString%
pause
You can see that "_2017-" hard-coded in on the 10th line. What I am looking to do in a purely logical sense on the rem line specifically:
set testString=%testString:%yearModified%=&rem.%
Because of the way this command modifies testString in-line, it makes it difficult to inject a variable into it. I have tried a huge combination of escapes and expansion settings to get the variable to take with no success so far. I have also tried to "build" the command as a string and attempt to call it and pipe the output to a variable:
#ECHO OFF
SETLOCAL DisableDelayedExpansion
set "testString=Machined_Cam-2286_2017-09-08.slddrw - SOLIDWORKS"
set "systemYear=2017"
set "yearModified=_%systemYear%-"
echo "%testString%" | find "%yearModified%" >NUL || goto :EOF
set "callCMD=%%testString:%yearModified%=^&rem.%%"
call %callCMD% > %testString%
echo %testString%
pause
This seems like such a simple issue, but my lack of understanding of string manipulation under DOS is apparent. As is stands, the rest of the script is running perfectly with the "_2017-" hard-coded. It would be nice to eliminite that bit of maintenance.
Any help or direction is appreciated.
Thank you.
May I show you another method of splitting. Replace your "Delimiterstring" with a proper Delimiter and use a for to split (for uses single-letter delimiters). Enabling delayed expansion helps, but is not neccessary. As you explicitely disabled it (you may have your reasons), I'll show you both:
#echo off
set "TestString=Machined_Cam-2286_2017-09-08.slddrw - SOLIDWORKS"
set "CutHere=_2017"
setlocal enabledelayedexpansion
for /f "delims=§" %%a in ("!TestString:%CutHere%=§!") do set Result=%%~a
echo enabled: %Result%
endlocal
setlocal disabledelayedexpansion
for /f "delims=§" %%a in ('call echo "%%TestString:%CutHere%=§%%"') do set Result=%%~a
echo disabled: %Result%
endlocal
Just be sure, you use a delimiter (§ here) that surely won't be in your string(s).
you are trying to control what you call using the contents of a variable
try using a temp file instead -
echo %%testString:%yearModified%=^&rem.%%" > temp.bat
call temp.bat > %testString%
You NEED delayed expansion for this type of operation, so enabe it.
I suggest to first get the remainder of the string
and remove this from the original string.
#ECHO OFF
SETLOCAL EnableDelayedExpansion
set "testString=Machined_Cam-2286_2017-09-08.slddrw - SOLIDWORKS"
set "systemYear=2017"
set "yearModified=_%systemYear%-"
echo "%testString%" | find "%yearModified%" >NUL || goto :EOF
set tempString=!testString:*%yearModified%=!
set testString=!testString:%yearModified%%tempstring%=!
echo %testString%
pause
Sample output:
Machined_Cam-2286
#echo off
setlocal EnableDelayedExpansion
set "testString=Machined_Cam-2286_2017-09-08.slddrw - SOLIDWORKS"
set "systemYear=2017"
set "yearModified=_%systemYear%-"
echo "%testString%" | find "%yearModified%" >NUL || goto :EOF
set testString=!testString:%yearModified%=^&rem.!
echo %testString%
pause
You shoud use a carrot(^) in Delayed Expansion mode.

How do I pull the middle of a string variable in batch?

I need to get a certain part of a string as one variable, and the rest as another variable. Ignor the "Script.CreateSub", that doesn't matter.
#Echo Off
Set String=Script.CreateSub(Start)
I need a variable named ComName to equal the first part of the input (Script.CreateSub) and a variable named Name that equals whatever is in between the parenthesis.
This is much the same answer as above but doesn't use delayed expansion, as it is not needed, and it will handle many poison characters.
#echo off
Set "String=Script.CreateSub(Start)"
for /f "tokens=1,2 delims=()" %%a in ("%String%") do set "ComName=%%a" & set "Name=%%b"
echo "%ComName%" , "%Name%"
This should do it:
#echo off
setlocal enabledelayedexpansion
Set String=Script.CreateSub(Start)
for /f "tokens=1,2 delims=()" %%a in ("%String%") do set function=%%a&set param=%%b
echo function=%function%
echo param=%param%
pause
See http://www.dostips.com/DtTipsStringManipulation.php#Snippets.SplitString for more info on this technique.

Find a string and replace specific letters in batch file

I have a to create an autosys job to trigger a batch file which would find a specific string and then replace the next 4 characters.
For example if file (with multiple lines) has below content and i am searching for played
the mad fox jumped of the old vine and
played soccer.
I should replace "socc" with "INFA"
I am new to batch files and my lead has been insisting that i do this using a batch file only. Any help would be greatly apprciated.
Thanks,
Joy
#echo off &setlocal
set "search=search string"
set "replace=kordo anstataui"
set "textfile=file.txt"
set "newfile=new.txt"
(for /f "delims=" %%i in ('findstr /n "^" "%textfile%"') do (
set "line=%%i"
setlocal enabledelayedexpansion
set "line=!line:%search%=%replace%!"
echo(!line!
endlocal
))>"%newfile%"
type "%newfile%"
Apparently you are searching for "played " with a space at the end, although your question is a bit vague.
See my hybrid JScript/batch utility called REPL.BAT that does regular expression search and replace. It works on any modern version of Windows from XP onward, and it does not require installation of any 3rd party executeables.
Using REPL.BAT:
type "yourFile.txt"|repl "played ...." "played INFA" >"yourFile.txt.new"
move /y "yourFile.txt.new" "yourFile.txt" >nul
I use this at times: sar.bat
::Search and replace
#echo off
if "%~3"=="" (
echo.Search and replace
echo Syntax:
echo "%~nx0" "filein.txt" "fileout.txt" "regex" "replace_text" [first]
echo.
echo.EG: change the first time apple appears on each line, to orange
echo."%~nx0" "my text old.txt" "my text changed.txt" "apple" "orange" first
echo.
echo.People that are familiar with regular expressions can use some:
echo.
echo.Change every line starting from old (and everything after it^) to new
echo."%~nx0" "my text old.txt" "my text changed.txt" "old.*" "new"
echo.
echo.If [first] is present only the first occurrence per line is changed
echo.
echo.To make the search case sensitive change
echo.IgnoreCase= from True to False
echo.
pause
goto :EOF
)
if "%~5"=="" (set global=true) else (set global=false)
set s=regex.replace(wscript.stdin.readall,"%~4")
>_.vbs echo set regex=new regexp
>>_.vbs echo regex.global=%global%
>>_.vbs echo regEx.IgnoreCase=True
>>_.vbs echo regex.pattern="%~3"
>>_.vbs echo wscript.stdOut.write %s%
cscript /nologo _.vbs <"%~1" >"%~2"
del _.vbs
Get yourself a copy of sed for your OS and call it from a batch file.
sed -e 's/socc/INFA/g' inputFileName > outputFileName
#echo off
setlocal EnableDelayedExpansion
set "search=played "
set replacement=INFA
set numChars=4
set line=the mad fox jumped of the old vine and played soccer.
rem The characters after the equal-signs are Ascii-254
for /F "tokens=1* delims=■" %%a in ("!line:%search%=■!") do (
set "rightPart=%%b"
set "line=%%a%search%%replacement%!rightPart:~%numChars%!"
)
echo !line!
Output:
the mad fox jumped of the old vine and played INFAer.
You must insert previous code into a loop that process the entire file. I left that part as an exercise for you...

Reading multiple text files and replacing a certain type of string in each of them using a batch file

I need to read all the text files from a directory and then replace a certain type of string (that comes in a line having 'volumelabel') with another (replacewith) in each of them. Following is the code snippet:
for /r %%g in (*.txt) do (
set filename=%%~nxg
for /F "tokens=3 delims=<>" %%i in ('findstr "volumelabel" !filename!') do (
set tobereplaced=%%i
)
echo !filename! has !tobereplaced! to be replaced by %replacewith%
for /F "tokens=*" %%a in (!filename!) do (
set str=%%a
set str=!str:!tobereplaced!=%replacewith%!
echo !str!>>new!filename!
)
)
Now the problem I am facing is it prints only tobereplaced (literally) in every line of the new files when
set str=!str:!tobereplaced!=%replacewith%!
echo !str!>>new!filename!
is used and prints tobereplaced=replacewith (values) when
set str=%str:!tobereplaced!=%replacewith%%
echo !str!>>new!filename!
is used. Can someone help me?
The least convoluted solution (in my humble opinion) is to use a subroutine to set str. Going more than one level deep of delayed expansion tends to cause severe brain hurt. Oh, you could probably fix your set str line by doing something like
call call call set str=%%%%str:%%tobereplaced%%=%replacewith%%%%%
...or similar. See what I mean about brain hurt? It's hard to follow the recursion.
So here's my suggestion for a solution. I also fixed another potential problem or two while I was at it. Since you're doing a recursive search for *.txt, I made the for loops able to work with whatever text files they find within subdirectories. I haven't tested this, so let me know if you get any grotesque errors.
#echo off
setlocal enabledelayedexpansion
set replacewith=whatever
for /r %%g in (*.txt) do (
set newfile=%%~dpng.new%%~xg
for /F "tokens=3 delims=<>" %%i in ('findstr "volumelabel" "%%g"') do (
set "tobereplaced=%%i"
echo %%~nxg has !tobereplaced! to be replaced by %replacewith%
rem combining your for loops this way makes the second only fire if the first is true
rem using "findstr /n" in your for loop preserves blank lines
for /F "delims=" %%a in ('findstr /n "^" "%%g"') do (
rem ...but you have to strip off the line numbers
set "str=%%a" && set "str=!str:*:=!"
rem "call :repl" to work around the delayed expansion conundrum
call :repl "!str!" "!tobereplaced!" "%replacewith%" str
echo !str!>>!newfile!
)
)
)
goto :EOF
:repl <line> <find> <replace> <var>
setlocal enabledelayedexpansion
set "line=%~1"
set "line=!line:%~2=%~3!"
set "%4=%line%"
goto :EOF
Caveat: If your text file contains exclamation marks, equal signs or carats, they might not make it into textfile.new.txt.
For what it's worth, if I were in your position, instead of using a batch file I would probably use sed (the binaries should be all you need). You wouldn't even need a script. You could do it as a one liner like this:
for /r %I in (*.txt) do sed -r "s/volumelabel/replacement/ig" "%I" > "%~dpnI.new%~xI"
By the way, see the last couple of pages of help for for an explanation of the %~dpnI sort of notation.

Resources