Page 1 of 1
function to write any string to a text file without manual escaping
Posted: 28 Jul 2016 17:16
by mirrormirror
sorry for all of the posts today - just asking a bunch of questions that have been on the backburner...
Looking for a function or macro that can safely write all strings to a text file - without having to manually escape characters. For example:
Code: Select all
set "x=1% 2% 3% 4^% 5% ) == & =. a! b! < c! d^! >>e! ^ ^ <<'n1 = n +2 -( )))>>"
ECHO %x%>file.txt
Obviously this doesn't work - and it gets even worse if the string has a double quote (") in the middle somewhere - like this line that I'm writing!
I'm just wondering if this is possible. Currently, if I have a string that may cause problems I use vbscript (script below) and call it like this (but this can be slow to invoke the vbscript engine for a large number of lines):
Code: Select all
qt=chr(34):pct=chr(37)
Set wshShell = WScript.CreateObject("WScript.Shell")
'WScript.Echo WScript.Arguments(0)
'WScript.Echo WScript.Arguments(1)
ArgCntOrig=WScript.Arguments.Count
IF ArgCntOrig=0 THEN CALL EndScript
str=""
'DIM ArgsInUse
'REDIM ArgsInUse(ArgCntOrig-1)
FullCmdLine=WScript.ScriptFullName
FOR x=1 to ArgCntOrig -1
'ArgsInUse(x)=WScript.Arguments(x)
'FullCmdLine=FullCmdLine & " " & WScript.Arguments(x)
str=str & wshShell.ExpandEnvironmentStrings(pct & WScript.Arguments(x) & pct)
NEXT
'str=wshShell.ExpandEnvironmentStrings(pct & WScript.Arguments(0) & pct)
myTxtFile=WScript.Arguments(0)
x=0
' TRIM TABS - SPACES and QUOTES from File Path-Name
DO WHILE x=0
x=1
myTxtFile=TRIM(myTxtFile)
IF LEFT(myTxtFile,1)=vbTAB THEN
myTxtFile=RIGHT(myTxtFile, LEN(myTxtFile)-1)
x=0
END IF
IF RIGHT(myTxtFile,1)=vbTAB THEN
myTxtFile=LEFT(myTxtFile, LEN(myTxtFile)-1)
x=0
END IF
IF LEFT(myTxtFile,1)=qt THEN
myTxtFile=LEFT(myTxtFile, LEN(myTxtFile)-1)
x=0
END IF
IF RIGHT(myTxtFile,1)=qt THEN
myTxtFile=LEFT(myTxtFile, LEN(myTxtFile)-1)
x=0
END IF
LOOP
Dim FSO
Set FSO = CreateObject("Scripting.FileSystemObject")
Set oFile = FSO.OpenTextFile(myTxtFile, 8, True)
oFile.WriteLine(str)
SUB EndScript
On Error Resume Next
oFile.Close
On Error Goto 0
Set FSO= Nothing
Set wshShell = Nothing
END Sub
Re: function to write any string to a text file without manual escaping
Posted: 29 Jul 2016 10:57
by penpen
After i've seen the
REM ro file trick, i created the $secho macro (loaded calling the "loadSEcho.bat") to do this:
"test.bat"
Code: Select all
@echo off
cls
setlocal
:: load macros $sEcho, $_sEcho
:: occupies filename "_sEcho.txt" in directory "."
call loadSEcho.bat
%$sEcho%(%%a %%b ()[]{}^=;!'+,`~ & |
)
(
%$sEcho%(%%a %%b ()[]{}^=;!'+,`~ & |
)
) > testing.tmp.txt
endlocal
goto :eof
"loadSEcho.bat":
Code: Select all
@echo off
:: define info header
::
:: This batch file is automatically created using "blockToMacro.bat".
:: You may find it on "www.dostips.com".
::
:: macro(s) loaded into memory by this batch file:
:: - $sEcho
::
::
:: supported modes of operation:
:: ---------------------------------------------+---+---+---+---
:: extensions (e/d: en/disabled) | e | e | e | d
:: delayed expansion (e/d: en/disabled) | e | d | d |e/d
:: run from command line (y/n: yes/no) |y/n| y | n |y/n
:: ---------------------------------------------+---+---+---+---
:: macro behaviour (l/e: load/executable) |l+e| l |l+e| -
::
::
:: This batch overwrites the following environment variable names
:: of the current context, and will finally undefine them:
:: - Eo
:: - To
:: - Ei
:: - Ti
::
::
:: This macro uses the REM to file trick:
:: https://www.dostips.com/forum/viewtopic.php?t=2836
::
:: The macro defined here, will overwritte the file ".\_sEcho.txt" without asking.
::
::
:: Author of this macro:
:: penpen from dostips
::
::
:: end define info header
:: define check for valid system state
::
:: If the extensions are disabled, the set command throws an "syntax error",
:: when assigning an equal sign ('='):
:: This is essential for complex macros, so the extensions MUST be enabled.
::
2> nul set "extensionsEnabled=true" || (
echo(Error: The extensions are disabled, no macro will be loaded into memory.
rem simulate: exit /b 1
rem if extensions are disabled the label :EOF is not found
call
goto exit
)
::
:: end define check for valid system state
:: extensions: enabled
:: define $sEcho
:: Safe echo:
:: Should display anything.
::
:: You have to add a closing round brackets in the next line.
:: The first character after this macro will be ignored,
:: and therefore could be anything:
:: But for optical reasons i recommend to use an opening bracket.
::
:: Test cases:
::
:: %$sEcho%(%%a %%b ()[]{}^=;!'+,`~ & |
:: )
::
:: %$sEcho%&%%a %%b ()[]{}^=;!'+,`~ & |
:: )
::
:: %$sEcho% %%a %%b ()[]{}^=;!'+,`~ & |
:: )
::
::
:: :: outputting to a file:
:: (
:: %$sEcho%(%%a %%b ()[]{}^=;!'+,`~ & |
:: )
:: ) > testing.txt
::
:: Bases on the REM to file trick, see:
:: https://www.dostips.com/forum/viewtopic.php?p=13002#p13002
::
:: The file used for this trick is ".\_sEcho.txt"
:: This file will be overwritten without asking
::
set "Eo=1"
if "!Eo!" == "1" (
set "Eo=^^^^^^^!"
set "Ei=^^^!"
set "To=^^^^"
set "Ti=^^"
) else (
set "Eo=!"
set "Ei=!"
set "To=^^"
set "Ti=^"
)
setlocal enableExtensions disableDelayedExpansion
set LF=^
set ^"\n=^^^%LF%%LF%^%LF%%LF%^<nul ^^^"
set ^"[=%%~#^<nul ^^^%LF%%LF%^<nul ^^^"
set ^"]=^<nul^^^%LF%%LF%^%LF%%LF%^<nul ^^^"
endlocal & (
REM ==================== define { // $sEcho ====================
for %%# in ("") do set $sEcho=@for %%a in ^("%%a"^) do @for %%a in ^(%%~a, 2^) do @if %%a == 2 ^(%\n%
^(type "_sEcho.txt" ^& del "_sEcho.txt"^) ^| @^(^>nul ^(for /L %%a in ^(1, 1, 10^) do pause^)^&findstr "%Ti%"^)%\n%
^) else ^>"_sEcho.txt" ^(%\n%
for %%a in ^(1, %%a, 3^) do @if %%a == 1 ^(%\n%
setlocal disableExtensions%\n%
set prompt=#%\n%
echo on%\n%
^) else if %%a == 3 ^(%\n%
echo off%\n%
endlocal%\n%
^) else for %%a in ^(%%a^) do rem .
REM ==================== } // $sEcho ====================
)
endlocal
set "Eo="
set "Ei="
set "To="
set "Ti="
::
:: end define $sEcho
::
:: All macros loaded to memory: return success (errorLevel == 0).
exit /b 0
:exit
penpen
Re: function to write any string to a text file without manual escaping
Posted: 29 Jul 2016 14:45
by jeb
@penpen
Nice usage of the REM trick.
Something similar is my
magicEcho macroThe magicEcho can even handle single percents (no doubling needed).
@mirrormirror
When you only want to echo a variable in a safe way, this is really easy with delayed expansion.
Delayed expansion is always safe against any special character, as after the delayed expansion no more parser phases occours.
Code: Select all
set "x=1% 2% 3% 4^% 5% ) == & =. a! b! < c! d^! >>e! ^ ^ <<'n1 = n +2 -( )))>>"
>file.txt ECHO(!x!
The echo( is only to protect the echo command against content like "ON" or "/?"
Re: function to write any string to a text file without manual escaping
Posted: 29 Jul 2016 15:50
by mirrormirror
One of the issues I run across is that I can read text lines from files fine but sometimes can't write out those same lines. I tried your example using this string but get the error you see in the output below:
Code: Select all
@ECHO OFF &SETLocal DISABLEDelayedExpansion
FOR /F "tokens=* delims=" %%a IN ('FINDSTR /R /C:"^" t.txt') DO (
set str=%%a
REM @ECHO %%a
SETLocal ENABLEDelayedExpansion
@ECHO !str!
@ECHO sending output -------------------------
t2.txt>ECHO(!str!
ENDLocal
)
Output:
Code: Select all
T:\>mtest2
1% 2% 3% 4^% 5% ) == & =. a! b! c! "text" " d^! e! ^ ^ 'n1 = n +2 -( )))\|t:\t3.txt| >>t4.txt
sending output -------------------------
The filename, directory name, or volume label syntax is incorrect.
t.txt contains only one line with the text:
1% 2% 3% 4^% 5% ) == & =. a! b! c! "text" " d^! e! ^ ^ 'n1 = n +2 -( )))\|t:\t3.txt| >>t4.txtand the file
t2.txt never gets created.
penpen - thank you for the code - I'll need to look at it later and try it out (jeb's was much shorter and easier to digest - but not his magicecho
)
Re: function to write any string to a text file without manual escaping
Posted: 29 Jul 2016 15:58
by jeb
Simple fix it:
First the redirect character then the filename
Re: function to write any string to a text file without manual escaping
Posted: 29 Jul 2016 16:06
by mirrormirror
First the redirect character then the filename
- maybe I have the onset of dyslexia !
Thank you - this is simple and easy. I thought certain characters would cause issues with redirection to a file but I guess I am wrong. Maybe I am getting redirect confused with pipe...
Re: function to write any string to a text file without manual escaping
Posted: 29 Jul 2016 16:30
by mirrormirror
And to add an example of where I had a prior problem here:
http://www.dostips.com/forum/viewtopic.php?f=3&t=7291I suppose I could simply echo out each line seperately (without parentheses) and not have to worry about escaping my parentheses "
^)"
I'll try it next time