Batch - String replacement with special characters - windows

I would like to replace a string in a file using a batch file.
The string is:
),(
And I want to replace it by:
),
(
I found several posts, like this one : "how-to-replace-substrings-in-windows-batch-file" but the example uses a dummy string with no special characters.
Thank you !
EDIT
Context: I use mysqldump to extract a database and I would like every line of the insert command to be on a new line for more visibility.
I don't want to use --extended-insert=false because it slows down reinsertion of the backup.
EDIT2
Example:
INSERT INTO `dummytable` (`dummycolumn`) VALUES (1),(2),(3);
I want it to be:
INSERT INTO `dummytable` (`dummycolumn`) VALUES (1),
(2),
(3);

Take a look at replacer.bat
call replacer.bat "e?C:\content.txt" "\u0022),(\u0022" "\u0022),\u000a(\u0022"
Edit without the quotes:
call replacer.bat "e?C:\content.txt" "),(" "),\u000a("
windows style
call replacer.bat "e?C:\content.txt" "),(" "),\u000D\u000a("
you can check also FindRepl and JRepl which are more sophisticated tools

This works for me:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET textFile=test.txt
TYPE NUL>tempOut.txt
FOR /F %%l IN (%textFile%) DO (
SET line=%%l
SET line=!line:"),("="),\n("!
ECHO !line!>>tempOut.txt
)
MOVE /y tempOut.txt %textFile%

In batch if the pattern are always same you could deal with tokens and delims like this:
#echo off
(echo INSERT INTO `dummytable` (`dummycolumn`^) VALUES (1^),(2^),(3^);
)>%TEMP%\_file.tmp
(FOR /F "tokens=1,2,3* delims=," %%a IN (%TEMP%\_file.tmp) do (
echo %%a,
echo %%b,
echo %%c
))>_output.txt
exit /b 0
output:
INSERT INTO `dummytable` (`dummycolumn`) VALUES (1),
(2),
(3);
Edit
I found another way from a npocmaka's post in stackoverflow
#echo off
setlocal disableDelayedExpansion
REM Creating a Newline variable (the two blank lines are required!)
set NLM=^
set NL=^^^%NLM%%NLM%^%NLM%%NLM%
setlocal enableDelayedExpansion
for /f "delims=" %%a in (%TEMP%\_file.tmp) do (
set "line=%%a"
set line=!line:,(=,%NL%(!
echo !line!
)
endlocal
endlocal
exit /b 0

Related

How Can I Replace Any Line by Its Line Number?

EDIT: After great help from #aschipfl, the code is %110 as functional as I wanted it to be! I did some extra research and made it easy to use with prompts for that extra %10 :P
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Create a prompt to set the variables
set /p _FILETYPE="What file type: "
set /p _LINENUM="Which line: "
set /p _NEWLINE="Make line say: "
rem // Start the loop, and set the files
for %%f in (*%_FILETYPE%) do (
set "_FILE=%%f"
echo "_FILE=%%f"
rem // To execute seperate code before the end of the loop, starting at ":subroutine".
call :subroutine "%%f"
)
:subroutine
rem // Write to a temporary file:
> "%_FILE%.new" (
rem /* Loop through each line of the original file,
rem preceded by the line number and a colon `:`:*/
for /F "delims=" %%A in ('findstr /N "^" "%_FILE%"') do (
rem // Store the current line with prefix to a variable:
set "LN=%%A"
rem /* Store the line number into another variable;
rem everything up to the first non-numeric char. is regarded,
rem which is the aforementioned colon `:` in this situation: */
set /A "NUM=LN"
rem // Toggle delayed expansion to avoid trouble with `!`:
setlocal EnableDelayedExpansion
rem /* Compare current line number with predefined one and replace text
rem in case of equality, or return original text otherwise: */
if !NUM! equ %_LINENUM% (
echo(!_NEWLINE!
) else (
rem // Remove line number prefix:
echo(!LN:*:=!
)
endlocal
)
)
rem // Move the edited file onto the original one:
move /Y "%_FILE%.new" "%_FILE%"
endlocal
exit /B
ORIGINAL QUESTION:
Doesn't matter whats in any of the lines already. I just want to be able to pick any line from a .txt and replace it with whatever I choose.
So for example: Maybe I have a bunch of .txt's, and I want to replace line 5 in all of them with "vanilla". And later choose to replace line 10 of all .txt's with "Green". And so on...
I've seen lots of people asking the same main question. But I keep finding situational answers.
"How do I replace specific lines?" "you search for whats already in the line, and replace it with your new text" -I cant have that. I need it to be dynamic, because whats in each "line 5" is different, or there's lots of other lines with the same text.
I had tried the only one answer I could find, but all it ended up doing is replace literally all lines with "!ln:*:=!", instead of echoing.
#echo off
setlocal disableDelayedExpansion
set "file=yourFile.txt"
set "newLine5=NewLine5Here"
>"%file%.new" (
for /f "delims=" %%A in ('findstr /n "^" "%file%"') do for /f "delims=:" %%N in ("%%A") do (
set "ln=%%A"
setlocal enabableDelayedExpansion
if "!ln:~0,6!" equ "5:FMOD" (echo(!newLine5!) else echo(!ln:*:=!
endlocal
)
)
move /y "%file%.new" "%file%" >nul
The following (commented) code should work for you:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_FILE=yourFile.txt"
set "_NEWLINE=NewLine5Here"
set /A "_LINENUM=5" & rem // (target line number)
rem // Write to a temporary file:
> "%_FILE%.new" (
rem /* Loop through each line of the original file,
rem preceded by the line number and a colon `:`:*/
for /F "delims=" %%A in ('findstr /N "^" "%_FILE%"') do (
rem // Store the current line with prefix to a variable:
set "LN=%%A"
rem /* Store the line number into another variable;
rem everything up to the first non-numeric char. is regarded,
rem which is the aforementioned colon `:` in this situation: */
set /A "NUM=LN"
rem // Toggle delayed expansion to avoid trouble with `!`:
setlocal EnableDelayedExpansion
rem /* Compare current line number with predefined one and replace text
rem in case of equality, or return original text otherwise: */
if !NUM! equ %_LINENUM% (
echo(!_NEWLINE!
) else (
rem // Remove line number prefix:
echo(!LN:*:=!
)
endlocal
)
)
rem // Move the edited file onto the original one:
move /Y "%_FILE%.new" "%_FILE%"
endlocal
exit /B
Besides the typo in EnableDelayedExpansion in your code, you do not even need a second for /F loop to get the line number, and you do not need to extract a certain number of characters from the prefixed line text.
Note that this approach fails for line numbers higher than 231 - 1 = 2 147 483 647.
...is replace literally all lines with "!ln:*:=!", instead of echoing.
But that's correct, because the FINDSTR /N prefixes each line with a line number before.
The !ln:*:=! only removes the line number again.
And the findstr trick is used to avoid skipping of empty lines or lines beginning with ; (the EOL character).
The !line:*:=! replaces everthing up to the first double colon (and incuding it) with nothing.
This is better than using FOR "delims=:" because delims=: would also strip double colons at the front of a line.
The toggling of delayed expansion is necessary to avoid accidential stripping of ! and ^ in the line set "ln=%%A"
To fix your code:
setlocal DisableDelayedExpansion
for /f "delims=" %%A in ('findstr /n "^" "%file%"') do (
set "ln=%%A"
setlocal EnableDelayedExpansion
if "!ln:~0,6!" equ "5:FMOD" (
set "out=!newLine5!"
) else (
set "out=!ln:*:=!"
)
echo(!out!
endlocal
)

Windows Batch - Find word in one string matching word in another string and capture output

While this may seem easy to some, I've struggled for hours on it.
I have a file:
MYFOLDER,JobE,JobD_ENDED_OK,
MYFOLDER,JobD,JobC_ENDED_OK,JobD_ENDED_OK
MYFOLDER,JobD,JobB_ENDED_OK,
MYFOLDER,JobC,JobA_ENDED_OK,JobC_ENDED_OK
MYFOLDER,JobB,JobA_ENDED_OK,JobB_ENDED_OK
MYFOLDER,JobA,,JobA_ENDED_OK
I need to loop through and find where token 4 in one line matches token 3 in another line and then echo a statement to a file. I am looking for an output file that shows this:
MYFOLDER_JobA_MYFOLDER_JobB matches JobA_ENDED_OK
MYFOLDER_JobA_MYFOLDER_JobC matches JobA_ENDED_OK
MYFOLDER_JobB_MYFOLDER_JobD matches JobB_ENDED_OK
MYFOLDER_JobC_MYFOLDER_JobD matches JobC_ENDED_OK
MYFOLDER_JobD_MYFOLDER_JobE matches JobD_ENDED_OK
I know it's a FOR loop with a DO, I am just not getting the rest of it.
Any assistance is greatly appreciated.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=U:\sourcedir"
SET "destdir=U:\destdir"
SET "filename1=%sourcedir%\q46510665.txt"
SET "outfile=%destdir%\outfile.txt"
(
FOR /f "usebackqdelims=" %%h IN ("%filename1%") DO (
SET "col4line=%%h"
SET "col4line=!col4line:,=|,|!"
FOR /f "tokens=1-4delims=," %%a IN ("!col4line!") DO IF "%%d" neq "|" (
FOR /f "usebackqdelims=" %%H IN ("%filename1%") DO (
SET "col3line=%%H"
SET "col3line=!col3line:,=|,|!"
FOR /f "tokens=1-4delims=," %%A IN ("!col3line!") DO (
IF "%%d|"=="%%C" (
SET "reportline=%%a_%%b_%%A_%%B matches %%C"
ECHO !reportline:^|=!
)
)
)
)
)
)>"%outfile%"
GOTO :EOF
You would need to change the settings of sourcedir and destdir to suit your circumstances.
I used a file named q46510665.txt containing your data for my testing.
Produces the file defined as %outfile%
For each line in the file, set a variable col4line to the entire line via %%h, then replace each , with |,| so that successive , will be separated. Tokenise on , and ignore any line which has simply | as its 4th token (ie last-column-empty).
Repeat the process for every line in the file this time through %%H into col3line (note case differential to use different actual metavariables) and if the third column matches the fourth column+| from the outer loop, assemble the report line from the tokens and output, removing the |s.

Joining a list of numbers in a .txt file with ,[space]

Hi I managed to get the code below to create a list of numbers and place a comma at the end of each number created However, it has proven to be quite the challenge to get them on the same line separated by a ,[space]
#ECHO OFF
setlocal EnableDelayedExpansion
set _Output=%UserProfile%\Desktop\NumGen.txt
::only change these three lines
set "start=1" ::starts from this number
set "amount=10" ::amount of files created
set "length=5" ::length of fileNames
set "join_with=, " ::what to join each number with
set /a "last=%start%+%amount%"
for /l %%i in (%start%,1,%last%) do (
set "folderName=0000000000%%i"
set "folderName=!folderName:~-%length%!%join_with%"
>>"%_Output%" ECHO.!folderName!
)
pause
so my output at the moment is
00001,
00002,
00003,
00004,
00005,
00006,
00007,
00008,
00009,
00010,
00011,
However I would like it to be
00001, 00002, 00003, 00004, 00005, 00006, 00007, 00008, 00009, 00010, 00011
I have windows 10 64bit. Any help will be appreciated
echo is not able to do that. But there is a workaround, (ab)using the set command:
for /l %%i in (1,1,5) do (
<nul set /p "=%%i, "
)
echo(
After a long break I decided to give this another bash and presto. Success :-)
::CallScript
#ECHO OFF
CALL :ScriptA
CALL :ScriptB
CALL :ScriptC
pause
goto :eof
:ScriptA
#ECHO OFF
setlocal EnableDelayedExpansion
set _Output=%UserProfile%\Desktop\NumGen.txt
::only change these three lines
set "start=1"
set "amount=10"
set "length=5"
set "join_with=, "
set /a "last=%start%+%amount%"
for /l %%i in (%start%,1,%last%) do (
set "folderName=0000000000%%i"
set "folderName=!folderName:~-%length%!%join_with%"
>>"%_Output%" ECHO.!folderName!
)
goto :eof
:ScriptB
#ECHO OFF
setlocal enableextensions enabledelayedexpansion
set "var="
for /f "usebackq delims=" %%a in ("%UserProfile%\Desktop\NumGen.txt") do set "var=!var!%%a"
echo %var%> "%UserProfile%\Desktop\NumList.txt"
goto :eof
:ScriptC
#ECHO OFF
del "%UserProfile%\Desktop\NumGen.txt"
goto :eof
This code determines the starting number, the amount of numbers, the length of the numbers and joins them with , "
Then ScriptB concatenates each number together with the , " and saves to NumList.txt
Lastly the script deletes the NumGen.txt file.
Stephan has one solution with SET /P. The other option is to build the entire string within an environment variable, and then write after the loop ends. This is significantly faster, but it will fail if the final string length exceeds ~8191 bytes.
set "str="
for /l %%i in (%start%,1,%last%) do (
set "folderName=0000000000%%i"
set "str=!str!!folderName:~-%length%!%join_with%"
)
>>"%_Output%" ECHO.!str!
You could remove the unwanted trailing , if you want:
>>"%_Output%" ECHO.!str:~0,-2!

How to extract the numbers after a character in windows batch files

Hi I do need to extract the last part of a string after the last dot
Example:
1.2.37 ==> I need the 37
1.2.567 ==> I need the 567
as you can see the number of characters after the dot is not fixed so expressions like
base=%fullver:~0,-2%
Can't be used. How can I achieve this?
#echo off
setlocal enableextensions disabledelayedexpansion
set "fullver=1.2.456"
for %%a in ("%fullver:.=\%") do set "base=%%~na"
echo %base%
The trick is to replace the dots with backslashes, process the string as a path and retrieve the name of the last element in it.
Alternatively, if all the elements need to be retrieved, instead of a for, a for /f is used to tokenize the variable using the dots as separators
#echo off
setlocal enableextensions disabledelayedexpansion
set "fullver=1.2.456"
for /f "tokens=1-3 delims=." %%a in ("%fullver%") do (
set "major=%%a"
set "minor=%%b"
set "build=%%c"
)
echo [%major%] [%minor%] [%build%]
I found the following question which actually tokenizes the string.
How to split a string in a Windows batch file?
May be you can try using this to delimit it with "." and take the last value stored in the string variable. Not sure if there is a simple way, but this works.
Here is an edited Version to fit your Needs:
#echo off
setlocal ENABLEDELAYEDEXPANSION
REM Set a string with an arbitrary number of substrings separated by semi colons
set teststring=1.2.5.234
for /f "tokens=1 delims=." %%a IN ("!teststring!") DO set firststring=%%a
echo !firststring!
REM Do something with each substring
:stringLOOP
REM Stop when the string is empty
if "!teststring!" EQU "" goto END
for /f "delims=." %%a in ("!teststring!") do set substring=%%a
REM Now strip off the leading substring
:striploop
set stripchar=!teststring:~0,1!
set teststring=!teststring:~1!
if "!teststring!" EQU "" goto stringloop
if "!stripchar!" NEQ "." goto striploop
goto stringloop
:END
echo !substring!
endlocal
I prefer MC ND's answer if you are looking for only the last node, or if you know how many nodes there are.
Here is a method to capture all nodes if the total number of nodes is unknown:
#echo off
setlocal enableDelayedExpansion
set "fullver=1.2.456"
:: Parse each node and store in an "array"
set cnt=0
for %%A in (%fullver:.= %) do (
set /a cnt+=1
set "node.!cnt!=%%A"
)
:: Show the results
for /l %%N in (1 1 %cnt%) do echo node.%%N = !node.%%N!
Another solution! This one gets the first and last parts of the string:
#echo off
setlocal
set "testString=1.2.5.234"
set "first="
for %%a in ("%testString:.=" "%") do (
if not defined first set "first=%%~a"
set "last=%%~a"
)
echo First: %first%
echo Last: %last%
As a bonus, this method correctly process special Batch characters that may appear in the string, excepting wild-cards.
You can use the below command to achieve what you want.
base=%fullver:~~4,3%
4 implies 4th digit i.e., 5 and 3 implies 3 digits from 4.
The output will be
567

Batch Scripting:search file, extract numbers, and copy into new file

I'm new to batch scripting and have a question. I was wondering if it's possible to search a .txt file by requirements and take data specified and copy into a new .txt file?
Like if I have 50 lines with 9 digit numbers and a bunch of other crap I don't need after them can I say,
"For any line beginning with a 1,2,3,4,5,6,7,8,or 9...take the first 9 digits and copy them into a new file, for all lines in the file???"
I thought this would be easier than trying to delete all the other stuff. Let me know if you know anything about how to do this! Thanks.
Here's an example of what one line looks like:
123456789#example
and I just need to extract the 9 digit numbers from about 50 lines of this.
You can use FINDSTR to filter out all lines that do not start with 9 digits. Then FOR /F can read the result, line by line. A variable is set, and a substring operation preserves just the first 9 digits.
#echo off
setlocal enableDelayedExpansion
(
for /f %%A in (
'findstr "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]" yourFile.txt'
) do (
set "ln=%%A"
echo !ln:~0,9!
)
)>newFile.txt
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
(
FOR /f "delims=" %%a IN (q24824079.txt) DO (
SET "line=%%a"
REM set DIGITS to the first 9 characters of LINE
SET "digits=9!line:~0,9!"
FOR /L %%z IN (0,1,9) DO SET "digits=!digits:%%z=!"
IF NOT DEFINED digits ECHO(!line:~0,9!
)
)>newfile.txt
GOTO :EOF
I used a file named q24824079.txt containing data for my testing.
Produces newfile.txt
You did not specfy what to do if the line was all-digits but has fewer than 9 characters. I chose to report that line.
Hopefully this helps getting the job done:
#echo off
setlocal enabledelayedexpansion
for /f %%e in (emails.txt) do (
echo Email: %%e
for /f "delims=# tokens=1" %%b in ("%%e") do (
set BEGIN=%%b
echo Name: !BEGIN!
set FIRST=!BEGIN:~0,1!
echo First char: !FIRST!
set /a NUMERIC=!FIRST!+0
echo Converted to number: !NUMERIC!
if !FIRST!==!NUMERIC! echo Yippieh!
echo.
)
)
Instead of echo Yippieh! append the email (%%e) to a file, e.g. like
echo %%e >> output.txt

Resources