Reputation: 3
I need to do a very simple thing: substitute one frase with another. This must be done by CMD batch file (for Windows 7). The frase to be subsitituted can be in any position in txt file line (and in many lines).
The problem is the frase to be substituted contains ":" and "!" characters. I am not very skilled in batch files (to put it mildly), though I spend some hours especially to learn about this specific problem. It looks very complicated for me. At last, by chance, I overided the issue, but... I feel it is a barbarity how I did it.
The real line with the frase which should be substituted is e.g.:
"21:12:45 WARNING: No video signal present!"
The frase which should be substituted is:
"WARNING: No video signal present!"
The frase, which it should be substituted with is:
"Recognition suspended"
I have found this code: https://www.computerhope.com/forum/index.php?topic=41188.0
It works fine, except cannot work with "!" as I see, and escape char "^" never works. But I noticed that although it doesn't work properly - it trims the exclamation mark. Here are real strings before (b) and after (a):
(b)20:42:18 WARNING: No video signal present!
(a)20:42:18 WARNING: No video signal present
So I add 2 other lines to the code and this does the thing. The whole code is now:
@echo off
setlocal enabledelayedexpansion
set txtfile=D:\wfc\testlib\test.txt
set newfile=D:\wfc\testlib\new_test.txt
if exist "%newfile%" del /f /q "%newfile%"
for /f "tokens=*" %%a in (%txtfile%) do (
set newline=%%a
set newline=!newline:No video signal present!=!
set newline=!newline:No video signal present=!
set newline=!newline:WARNING:=Suspend recognition!
echo !newline! >> %newfile%
)
First crucial line cuts "!", second line substitutes "No video signal present" with nothing (trims it), third line substitutes the rest "Warning:" with desirable "Suspend recognition".
And at the end I have:
(b)20:42:18 WARNING: No video signal present!
(a)20:42:18 Suspend recognition
I feel this could be done elegantly. Besides I am not sure, if my way is not dangerous for some reason (data damage etc.). Please help.
Upvotes: 0
Views: 121
Reputation: 34919
Yes, this can be done easier.
First of all, it is not the line set newline=!newline:No video signal present!=!
that removes the !
character, but it is the line set newline=%%a
, because there is delayed variable expansion enabled when the for
variable reference %%a
is expanded, which happens before delayed expansion, hence an orphaned exclamation mark appears that is simply removed.
The key to success is to disable delayed expansion during expansion of %%a
and to enable it afterwards. In the sub-string replacement syntax the :
does not cause any problems; neither does the !
in the search string, given it is not the first character. So the following code should work:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "txtfile=D:\wfc\testlib\test.txt"
set "newfile=D:\wfc\testlib\new_test.txt"
> "%newfile%" (
for /F usebackq^ delims^=^ eol^= %%a in ("%txtfile%") do (
set "newline=%%a"
setlocal EnableDelayedExpansion
echo(!newline:WARNING: No video signal present!=Recognition suspended!
endlocal
)
)
endlocal
exit /B
I also changed the following items:
set
by using quotes to avoid trouble with some special characters;newline
, so did the string manipulation directly in the echo
line;usebackq
option;tokens=*
by the delims=
option in order to keep leading white-spaces; to avoid loss of lines that begin with ;
due to the default eol
option, I used the odd-looking unquoted option string syntax as this is the only way (!) to have no delims
and eol
defined at the same time (you cannot write "delims= eol="
as this would define "
as the eol
character; "eol= delims="
would define the SPACE, and "eol=delims="
the d
);for
loop, so no initial file deletion necessary, and the performance is a lot better, because the output file has to be opened and closed once only, not in every iteration;echo Text > "file.ext"
returns a trailing SPACE (actually the one in front of >
); this is avoided by the above item; in general, this can be avoided when using the reversed redirection syntax > "file.ext" echo Text
;echo !VAR!
returns ECHO is on|off.
in case variable VAR
is empty; to avoid this or other unexpected output, the odd-looking but safe syntax echo(!VAR!
is used;%
) expansion when delayed expansion is enabled to avoid loss of !
;To keep empty lines that appear in the original file, change the code to this:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "txtfile=D:\wfc\testlib\test.txt"
set "newfile=D:\wfc\testlib\new_test.txt"
> "%newfile%" (
for /F "delims=" %%a in ('findstr /N /R "^" "%txtfile%"') do (
set "newline=%%a"
setlocal EnableDelayedExpansion
set "newline=!newline:WARNING: No video signal present!=Recognition suspended!"
echo(!newline:*:=!
endlocal
)
)
endlocal
exit /B
The findstr
command is used to prefix every line of the input file by a line number plus a colon (/N
option). Then the sub-string replacement is done. Finally, everything up to and including the first :
, hence the line number prefix becomes removed.
Upvotes: 1
Reputation: 16236
Substituting a phrase is pretty easy to do in a .bat file script.
powershell -NoLogo -NoProfile -Command ^
"Get-Content -Path '.\subfrase-in.txt' |" ^
"ForEach-Object { $_ -replace 'WARNING: No video signal present!', 'Recognition suspended' }"
Upvotes: 0