I found a example of what I wanted to do online, which was search a text file for a string and replace only that string and write out to a file. Which sort-of works...
The script does replace the correct text. But, its printing line numbers, which I don't want. However, if I remove the \n flag from findstr, it only prints lines containing data, and lines that aren't comments *(i.e. beginning with ";;").
How do I use findstr to print all the lines without the line numbers?
#echo off &setlocal
set "search=string to replace"
set "replace=replace string with me"
set "textfile=input.ini"
set "newfile=output.ini"
(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%"
The /n switch is required to keep the empty lines, so if want the empty lines in input be copied to the output you should not remove /n switch from findstr otherwise you do not need findstr and can directly read file with FOR. instead you can remove the line numbers by this modified code of yours:
#echo off
setlocal
set "search=string to replace"
set "replace=replace string with me"
set "textfile=input.ini"
set "newfile=output.ini"
(for /f "tokens=1* delims=:" %%i in ('findstr /n "^" "%textfile%"') do (
if "%%j" NEQ "" (
set "line=%%j"
setlocal enabledelayedexpansion
echo(!line:%search%=%replace%!
endlocal
) else (
echo(
)
))>"%newfile%"
type "%newfile%"
Also there is no need for set "line=!line:%search%=%replace%!" you can directly pass !line:%search%=%replace%! to echo
Or you can get ride of findstr altogether and simply write the FOR loop as below but you will loos empty lines
(for /f "usebackq delims="eol^= %%i in ("%textfile%") do (
set "line=%%i"
setlocal enabledelayedexpansion
echo(!line:%search%=%replace%!
endlocal
))>"%newfile%"
Please note that in "usebackq delims="eol^= there must be no spaces between the quotation mark(") and eol. It is not a typo.
This is to disable the default eol character(;) so the lines that beginning semicolon(;) will not be ignored by FOR /F command
Related
I cannot figure out how to correctly identify an empty/undefined variable having two semicolon one after one other or the line that starts with it.
This is the cycle:
for /F "delims=; tokens=1-7" %%m IN (testlist.txt) DO echo FUNCGROUP=%%r a=%%m b=%%n c=%%o d=%%p e=%%q f=%%s
I also tried adding "eol=;" and "......eol=" without success.
This is content of the first line of the file testlist.txt:
;xxxxxx;Active;;FALSE;con ter - dong;HWID000001;Item;sites/coll-
The result I need is, for the first cycle:
a=
b=xxxxxx
c=Active
d=
e=FALSE
f=con ter - dong
g=HWID000001
Thanks for any help.
To achieve that, you need to put a "NULL value" for empty fields in the lines of the file.
As there is no direct string substitution utilities with batch, you have to make substitutions beforehand to create "empty" fields. I suggest you to use a "NULL" character for empty fields like unbreakable space (Alt+0160).
In your case, this gives :
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
for /F "eol= tokens=*" %%l in (file.txt) DO (
SET "LINE=%%l"
SET "LINE=###!LINE:;;=; ;!###"
SET "LINE=!LINE:###;= ;!"
SET "LINE=!LINE:;###=; !"
SET "LINE=!LINE:###=!"
for /F "delims=; tokens=1-7" %%m in ("!LINE!") DO (
SET "RES=FUNCGROUP=%%r a=%%m b=%%n c=%%o d=%%p e=%%q f=%%s"
echo !RES: =!
)
)
Note that the SET "LINE=###!LINE:;;=; ;!###", SET "LINE=!LINE:###;= ;!" and the SET "LINE=!LINE:;###=; !" sections use the unbreakable space (Alt+0160) and replace beginning ";" with "Alt+0160;", the ending ";" with ";Alt+0160" and any following ";;" with ";Alt+0160;". The for loop parses then correctly the line, and next you just have to remove the unbreakable space to get "empty" variables.
EDIT: As brightly suggested by #jeb in the comments, you can also use quotes to handle empty fields. Each for loop variables can be then directly and simply unquoted.
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
for /F "eol= tokens=*" %%l in (file.txt) DO (
SET "LINE=%%l"
SET "LINE=###^"!LINE:;=^";^"!^"###"
SET "LINE=!LINE:###^";=^"^";!"
SET "LINE=!LINE:;^"###=;^"^"!"
SET "LINE=!LINE:###=!"
for /F "delims=; tokens=1-7" %%m in ("!LINE!") DO (
echo FUNCGROUP=%%~r a=%%~m b=%%~n c=%%~o d=%%~p e=%%~q f=%%~s
)
)
Unfortunately, you have not provided sufficient information for what you intend to do with your empty field, so this is only a demonstration to provide you with output similar to that which you've indicated in your question:
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
For /F "Delims==" %%G In ("(Set Field[) 2>NUL") Do Set "%%G="
Set "i=0"
For /F UseBackQ^ Delims^=^ EOL^= %%G In ("testlist.txt") Do Call :GetFields "%%G"
Pause
GoTo :EOF
:GetFields
Set "Record=%~1"
Set /A i += 1
SetLocal EnableDelayedExpansion
Set "Index=1"
Set "Field[!Index!]=%Record:;=" & Set /A Index +=1 & Set "Field[!Index!]=%"
Echo(&Echo Record !i!
For /L %%G In (1,1,!Index!) Do If Not Defined Field[%%G] (Echo Field[%%G]=) Else Set Field[%%G]
Exit /B
I want to make it so that the empty lines are also outputted. For eg, this is my example.txt file.
Hello
This is a text file. Hello World!
And my code to run it is,
for /f "delims=" %%a in (%cd%\example.txt) DO (
echo. %%a
)
But it doesnt show the empty lines and instead shows it like
Hello
This is a text file. Hello World!
How do I make it so it shows the empty line too? Thanks!
FOR /F ignores empty lines, but you can use findstr to prefix each line with a line number, then there aren't empty lines anymore.
setlocal EnableDelayedExpansion
FOR /F "delims=" %%L in ('findstr /N "^" "%~dp0\example.txt"') DO (
set "line=%%L"
set "line=!line:*:=!" & rem Remove all characters to the first colon
echo(!line!
)
The problem with delayed expansion is that it destroys all ! and ^ characters from your file.
Therefore, you could toggle the mode.
setlocal DisableDelayedExpansion
FOR /F "delims=" %%L in ('findstr /N "^" "%~dp0\example.txt"') DO (
set "line=%%L"
setlocal EnableDelayedExpansion
set "line=!line:*:=!" & rem Remove all characters to the first colon
echo(!line!
endlocal
)
I have a batch file I'm using to search for a piece of text and replace it with another. It works, but what's happening is that when the 'new' file is created, anything after an exclamation mark is deleted.
So original file
Hello! I have some cheese
Just becomes
Hello
Although the text I am trying to replace is fine.
I understand that since I'm using delayed expansion I need to somehow escape the exclamation marks with ^^! but can't figure out where to do this. Adding it at the echo just echoes the ^^! literally.
Any help would be appreciated.
set "rootname=Common Filename"
set "replace="old">"
set "replaced="new">"
set "source="%rootname%_unqiue_suffix.txt""
set "target=Fixed\%SOURCE%"
setlocal enableDelayedExpansion
(
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" %source%') do (
set "line=%%b"
if defined line set "line=!line:%replace%=%replaced%!"
echo(!line!
)
) > %target%
endlocal
To avoid loss of exclamation marks, enable delayed expansion only when it is really needed and expand normal % variables and for meta-variables only when delayed expansion is disabled:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "rootname=Common Filename"
set "replace="old">"
set "replaced="new">"
set "source=%rootname%_unqiue_suffix.txt"
set "target=Fixed\%source%"
(
for /F "tokens=1* delims=:" %%a in ('findstr /N "^" "%source%"') do (
set "line=%%b"
setlocal EnableDelayedExpansion
if defined line set "line=!line:%replace%=%replaced%!"
echo(!line!
endlocal
)
) > "%target%"
endlocal
This code still causes trouble in case the variables replace and replaced contain !-signs, because they are percent-expanded.
I am writing a .bat program that will find and replace text in a file. The problem that I am having is that it is removing blank lines and left justifying the other lines. I need the blank lines to remain and the new text to remain in the same location. Here is what I have wrote, and also the result. Can anybody please help.
program:
#ECHO OFF
cls
cd\
c:
setLocal EnableDelayedExpansion
For /f "tokens=* delims= " %%a in (samplefile.tx) do (
Set str=%%a
set str=!str:day=night!
set str=!str:winter=summer!
echo !str!>>samplefile2.txt)
ENDLOCAL
cls
exit
samle File:
this line is the first line in my file that I am using as an example.This is made up text
the cat in the hat
day
winter
below is the result:
this line is the first line in my file that I am using as an example.This is made up text
the cat in the hat
night
summer
I need the lines, spaces and new text to remain in the same position while making the text replacement. Please help
Your use of "tokens=* delims= " will trim leading spaces. Instead, use "delims=" to preserve leading spaces.
FOR /F always skips empty lines. The trick is to insert something before each line. Typically FIND or FINDSTR is used to insert the line number at the front of each line.
You can use !var:*:=! to delete the the line number prefix from FINDSTR.
Use echo(!str! to prevent ECHO is off message when line is empty
It is more efficient (faster) to redirect only once.
#echo off
setlocal enableDelayedExpansion
>samplefile2.txt (
for /f "delims=" %%A in ('findstr /n "^" samplefile.txt') do (
set "str=%%A"
set "str=!str:*:=!"
set "str=!str:day=night!"
set "str=!str:winter=summer!"
echo(!str!
)
)
This still has a potential problem. It will corrupt lines that contain ! when %%A is expanded because of the delayed expansion. The trick is to toggle delayed expansion on and off within the loop.
#echo off
setlocal disableDelayedExpansion
>samplefile2.txt (
for /f "delims=" %%A in ('findstr /n "^" samplefile.txt') do (
set "str=%%A"
setlocal enableDelayedExpansion
set "str=!str:*:=!"
set "str=!str:day=night!"
set "str=!str:winter=summer!"
echo(!str!
endlocal
)
)
Or you could forget custom batch entirely and get a much simpler and faster solution using my JREPL.BAT utility that performs regular expression search and replace on text. There are options to specify multiple literal search/replace pairs.
jrepl "day winter" "night summer" /t " " /l /i /f sampleFile.txt /o sampleFile2.txt
I used the /I option to make the search case insensitive. But you can drop that option to make it case sensitive if you prefer. That cannot be done easily using pure batch.
#ECHO Off
SETLOCAL
(
FOR /f "tokens=1*delims=]" %%a IN ('find /n /v "" q27459813.txt') DO (
SET "line=%%b"
IF DEFINED line (CALL :subs) ELSE (ECHO()
)
)>newfile.txt
GOTO :EOF
:subs
SET "line=%line:day=night%"
SET "line=%line:winter=summer%"
ECHO(%line%
GOTO :eof
Thi should work for you. I used a file named q27459813.txt containing your data for my testing.
Produces newfile.txt
Will not work correctly if the datafile lines start ].
Revised to allow leading ]
#ECHO Off
SETLOCAL
(
FOR /f "delims=" %%a IN ('type q27459813.txt^|find /n /v "" ') DO (
SET "line=%%a"
CALL :subs
)
)>newfile.txt
GOTO :EOF
:subs
SET "line=%line:*]=%"
IF NOT DEFINED line ECHO(&GOTO :EOF
SET "line=%line:day=night%"
SET "line=%line:winter=summer%"
ECHO(%line%
GOTO :eof
I have this code to replace some text in JS file:
#echo off &setlocal
set "search=showLog: true"
set "replace=showLog: false"
set "textfile=globalsDebugTest.js"
set "newfile=new.js"
(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%"
The problem with this script is that it adds a line number in every new line.
I just want to replace this string: "showLog: true" with this: "showLog: false".
Any idea how to do it?
for /f "tokens=1*delims=:" %%h in ('findstr /n "^" "%textfile%"') do (
(note the addition of a tokens= phrase, delims is assigned : and the loop metavariable is changed to h.)
adding the tokens= means the metavariable h receives the number before the delimiter (colon) and i the remainder of the line after the colon. This keeps the changes on one line.
Another option would be to simply drop the /n from the findstr which will have the consequence of removing all empty lines from the output.