Is there an equivalent to 'cut -c' in Windows cmd.exe? - windows

I have some files of fixed line size, fixed field size that I need to extract information from. Nornmally, I'd use Cygwin (cut et al), but that's not an option in this case due to (boneheaded) management policies I can't change. It has to be done using standard XP toolset included with Windows.
I need to extract the 10 characters at offset 7 and 4 characters at offset 22 (zero-based), and output them to a file but with a slight twist:
The first field may have a negative, positive, or no sign (at the start or end). The sign should be moved to the front, or removed totally if it's positive.
The second field should have leading and trailing spaces removed.
For example:
1 2 3 <- ignore (these lines not in file,)
0123456789012345678901234567890123456789 <- ignore ( here only for info.)
xxxxxxx 15.22-yyyyyABCDzzzzzzzzzzz...
xxxxxxx 122.00+yyyyy XX zzzzzzzzzzz...
xxxxxxx 9yyyyyYYY zzzzzzzzzzz...
should produce (< indicates end of line):
-15.22,ABCD<
122.00,XX<
9,YYY<

If you working with modern windows, you are not restricted to cmd.exe commands natively, you can use vbscript. If your policy is not to use vbscript either, then I guess you should sack your management :)
Set objFS=CreateObject("Scripting.FileSystemObject")
strFile = "c:\test\file"
Set objFile = objFS.OpenTextFile(strFile)
strFirstLine = objFile.ReadLine
Do Until objFile.AtEndOfStream
strLine= objFile.ReadLine
var1 = Mid(strLine,10) ' do substring from position 10 onwards
' var2 = Mid (strLine,<pos>,<length>) ' get next offset and save to var2
WScript.Echo var1 & var2 ' print them out.
Loop
Basically, to "cut" characters of a string, you use Mid() function. please look at the vbscript documentation to find out more.
Save the above as test.vbs and, on the command line, do
c:\test> cscript /nologo test.vbs > newfile
Of course, "substring" can also be done with pure cmd.exe but I will leave it to some others to guide you.
Update by Pax: Based on this answer, I came up with the following which will be a good start:
option explicit
dim objFs, objFile, strLine, value1, value2
if wscript.arguments.count < 1 then
wscript.echo "Usage: process <input-file>"
wscript.quit
end if
set objFs=createObject("Scripting.FileSystemObject")
set objFile = objFs.openTextFile(wscript.arguments.item(0))
do until objFile.atEndOfStream
strLine= objFile.readLine
value1 = trim(mid(strLine, 8, 10))
value2 = trim(mid(strLine, 23, 4))
if right(value1,1) = "-" then value1 = "-" & left(value1,len(value1)-1)
if right(value1,1) = "+" then value1 = left(value1,len(value1)-1)
if left(value1,1) = "+" then value1 = mid(value1,2)
wscript.echo value1 & "," & value2
loop
This matches all the requirements we had. We can make the offsets and lengths into command-line arguments later.
End update.

This site has some pointers on how to extract substrings in cmd.exe: http://www.dostips.com/DtTipsStringManipulation.php
That site suggests that you can use
%varname:~2,3%
to subscript a variable. This seems to fill your needs, except you now have to get each line into a variable.
Next you want to look at the ghastly for loop syntax and if and branching (you can goto :labels in batch).
This stuff is all rather ugly, but if you really have to go there...
Here is a page in SO on looping through files and doing stuff to them: How do you loop through each line in a text file using a windows batch file?

Here's a small script (needs to be in a BAT/CMD file) expanding on what Daren Thomas suggested:
#echo off
setlocal
set key=HKCU\Software\Microsoft\Windows\CurrentVersion\Ext\Stats\{D27CDB6E-AE6D-11CF-96B8-444553540000}\iexplore\AllowedDomains
echo.
echo Liste der fuer Flash im IE zugelassenen Domaenen:
echo =================================================
for /f "usebackq tokens=11 delims=\" %%l in (`call reg query "%key%" /s`) do echo. %%l
echo.
endlocal
The FOR loop is the central part. Note the use of command modifiers in double quotes. I specify tokens=11 because I'm only interested in the subkeys of AllowedDomains, which is at position 10.
Be sure to read the help in for /?. Daren is right when he says this stuff is all rather ugly. And it easily breaks down on modification. There's a lot of non-intuitive subtleties with cmd.exe script syntax.
By the way, the GUID is the COM class ID for the Shockwave Flash Add-on. It's been around since at least 2001 so might well continue to be relevant for the foreseeable future. The purpose of the script is to list the domains where Flash, which I prefer to block by default, has been allowed.

Related

How can I convert this VBS script to Bash?

I have this code in VBS that I need to rebuild in Bash. This is a snippet of a larger script that I have to convert. Can someone please help me with this?
I have read a lot of documentation on Bash in the last two days that I have been working on the larger script but am still not sure how to go about doing this. My coworker/trainer essentially handed me this and told me to use Google to learn Bash in order to do this. I feel it's also important to note that I am not familar with VBScript either.
Function Build_Param_Array()
Set objFSO = WScript.CreateObject("Scripting.Filesystemobject")
Set ReadFile = objFSO.OpenTextFile("Param_List.txt")
While Not ReadFile.AtEndOfStream
thisline = ReadFile.ReadLine
Pcount = Pcount + 1
ReDim preserve arrParam(Pcount)
If Not Right(thisline,1) = "|" Then thisline = thisline & "|"
arrParam(Pcount) = thisline
Wend
End Function
Not a vbs guru, but winging it for a general guess, it looks like it reads Param_List.txt, makes sure each line ends with a pipe character, then pushes it onto an array (arrParam).
typeset -a arrParam # declare an array
while read l # read each line from stdin into l
do arrParam+=("${l%|}|") # push the line onto the array, assuring a |
done < Param_List.txt # put the file on the loop's stdin
$l is the line read. ${l%|} is the line read, with any pipe as the last character removed; thus "${l%|}|" explicitly removes a pipe if there was one, then adds one whether or not one was removed.

How to output multiple user input values into a single variable in BATCH using Windows 7?

SOLVED!
Update: It figures moments after posting for help which is something I never do I'd figure it out...I tend to over think things, and that was the case here, it was just so simple! >.<
Solution:
(This worked under Windows 7 Ultimate 64 Bit)
Set var=
Set var=SomeText %var1% %var2% %var3%
Echo %var% > output.txt
See an explanation in my answer below.
I've been searching and trying several posts here similar to my question for hours with no success. I'm not new to Programming in BATCH but I have memory problems and thus can't always remember things. It also doesn't help that I program in other languages on other platforms which usually means I'm trying to use *nix shell commands in my Windows Batch scripts >.<
I've gotten quite close with some examples but nothing that works as needed.
Ideally, I'd like this work to work on Windows 7, 8, 8.1, Vista and 10 as that is the intended target.
This is what I need to accomplish:
The user will answer a series of questions, each question is stored into a .txt file (or variable if you prefer. I just used text files because of a past project where I ran into issues with variables that couldn't be solved and text files worked). The lines in each text file will need to be output into a single text file, on a single line which will then be read back in as a variable and run. Again, you could just use and combine the variables in your example if that's easier for you or both of us ;P
This is a snippet example of how I was doing it
SET file1=
SET /P file1=file1:%=%
ECHO %file1% > file1.txt
Then
copy /b file1.txt + file2.txt + file3.txt + file4.txt output.txt
Here is how I'd like the result to look
toolkit /S "C:\ToolKit Bravo\Data\etc" "D:\ToolKit Bravo\Data\Ops"
The "" quotation marks are necessary. The output MUST be EXACTLY as shown above for the example I've given. The "/S" & paths are variable NOT fixed!
Here is the best I've been able to come up with using variables..
"toolkit /S "C:\ToolKit Bravo\Data\etc" "D:\ToolKit Bravo\Data\Ops""
Update 2 - An explanation as requested:
The paths in the above example directly above this are not fixed! This was an Example Only. "toolkit" is fixed, this doesn't change. "/S" is an option selected by the user to pass on to the "toolkit". Both the source and destination paths are again input by the user in "quotation" marks. They're not fixed paths.
As you can see the result is surrounded by quotations which is NOT acceptable. And Please remember, I NEED the quotations around the paths in the end result, so removing them all is NOT an option!
Any help is greatly appreciated! Thank you for your time.
Just take all of the characters between the quotes.
SET X="toolkit /S "C:\ToolKit Bravo\Data\etc" "D:\ToolKit Bravo\Data\Ops""
ECHO %X%
SET Y=%x:~1,-1%
ECHO %Y%
Solution:
This solved my problem under Windows 7 Ultimate 64 Bit
Set var=
Set var=SomeText %var1% %var2% %var3%
Echo %var% > textfile.txt
Using the SET command I first made sure the variable or var for short was empty. Using this command:
Set var=
I then proceeded to create my variable using all of the other variables I had created and wanted to combine using this line of code:
Set var=SomeText %var1% %var2% %var3%
Note that I have preceded the variables with "SomeText". This is where I'll place the name of the .exe I'm passing the arguments to, but it can be anything you want included. I also need spaces between each variable so I've left spaces between them in the example code. If you don't want the spaces simply remove them, and you'll have 1234, instead of 1 2 3 4.
Finally I send the combined variable out to a .txt file.
Echo %var% > textfile.txt
However, you could also simply call the new variable now like this:
%var%

get an unknown string between two strings and save it in a var (Windows script)

The thing is that I want to do this JUST by using Windows bash utils (so it can be easily used without other applications like Cygwin/grep on other workstations).
Also this command will be in a larger script that uses the extracted string as a part of a filename.
ex: this is the line in the searched file
" <DataVersion>A0C2</DataVersion>"
A0C2 is the string that I need but it can have a different value like X1Z4 but is always 4 alfanumeric characters long.
<DataVersion> and </DataVersion> are always present.
Also the line may occur more than once but I only need the first to be considered.
I found out in the mean time the answer to my own question.
set ROW=
set VERSION=
for /f %%i in ( 'findstr "<DataVersion>" file.txt' ) do #set ROW=%%i
set VERSION=%ROW:~x,y%
where:
x is the number of characters you want to skip in ROW and
y is the number of characters you want to save in VERSION
so in case
findstr "<DataVersion>" file.txt
returns and sets ROW to this value:
<DataVersion>AX23</DataVersion>
then:
set VERSION=%ROW:~14,4%
will set VERSION to AX23

I'm trying to timestamp data from stdin (into a log file) using a Windows Batch file

I'm collecting data from an API using a DOS port of wget to generate data for a log file (which will be analysed at a later date). The API provides all the information I need except a current time (it provides a time at the start of the stream of data but not again after that).
The API provides, typically 10 lines of data initially and then a line every 20-30 seconds.
I'm trying to timestamp this output and copy it to a log file - I don't mind if the timestamp is on the same line as the rest of the output or the line before.
I first started with this batchfile:
addtimes.bat:
#echo off >nul
:start
set /p input="":
echo %time%
echo %input%
goto:start
(called as "wget..... | addtimes.bat > log.log")
However this dropped data comping in - the beginning of many lines of data were lost.
I've looked on here and realised I should use a for loop.
addtimes2.bat:
#echo off
cls
setlocal EnableDelayedExpansion
for /F "tokens=*" %%a in ('more') do (
echo !time! %%a )
)
I've tried with and without Enabling Delayed Expansion.
I don't seem to be able to pass information one line at a time with a different timestamp - all my lines get identical timestamps once I close the datastream.
Typical input data is of the form:
[1,"219","265",14528,1359031137000,1359031137000]
[1,"6594","358",18188,1359031019000,1359031019000]
[1,"690","94",15920,1359031534000,1359031534000]
[1,"25164","102",2129,1359031457000,1359031457000]
[1,"3488","329",2109,1359030868000,1359030868000]
[1,"37247","6",11506,1359031223000,1359031223000]
You may notice there are UTC times in the data but they are not the current time.
I don't believe you can get the result you want using pure native batch. The reason why all your times are the same is that the FOR /F loop does not process any lines of input until the entire input stream has been buffered (the command on the left of the pipe has finished). The FOR /F command waits until all the input has been received, and then dumps every line in one mad rush. If the input stream is large enough, you will get slight variations in time, but nothing that comes close to representing when the original command generated each line.
Here is a hybrid JScript/batch script that does what you want. It works fine as a straight JScript file, but then you need to explictly use CSCRIPT. The hybrid approach makes the utility more convenient.
Call it addtimes.bat and use it just as you were before.
#if (#X)==(#Y) #end /* Harmless hybrid line that begins a JScript comment
::************ Batch portion ***********
#echo off
cscript //E:JScript //nologo "%~f0"
exit /b 0
************* JScript portion **********/
while (!WScript.StdIn.AtEndOfStream) {
var ts = new Date()
var ms = (ts.getTime() % 1000)
WScript.Stdout.WriteLine(
ts.getFullYear() + "-" +
((ts.getMonth()<9)?"0":"") + (ts.getMonth()+1) + "-" +
((ts.getDate()<10)?"0":"") + ts.getDate() + " " +
((ts.getHours()<10)?"0":"") + ts.getHours() + ":" +
((ts.getMinutes()<10)?"0":"") + ts.getMinutes() + ":" +
((ts.getSeconds()<10)?"0":"") + ts.getSeconds() + "." +
((ms<10)?"00":((ms<100)?"0":"")) + ms + " - " +
WScript.StdIn.ReadLine()
);
}
EDIT
wmz has a very clever and dangerous solution. That solution can be simplified - There is no need to muck with Autorun.
Warning - as wmz said, the solution below can have very bad consequences if any line in the output starts with an executable command or program name! I do not recommend actually using this solution, but I find it very interesting.
(echo #prompt $D $T -$S & YourCommandHere )|cmd 2>nul|findstr /rbc:"../../.... ..:..:..\... - " >log.log
The FINDSTR pipe is added to strip out the CMD header info, the initial PROMPT command, and the unwanted blank line that CMD inserts after each "command". The FINDSTR regex may need to change to match the specifics of your chosen prompt and your locale.
Please be warned: this may have a lot of side effects (or may not work at all, or make your system unstable etc.) and is not tested. It's more of exercise in batch than anything else
EDIT: See debenham's answer for refined way of using this idea.
set prompt to time (prompt $T) or date time if you prefer (prompt $D $T). You will have to do it in Autorun key in Registry (HKEY_CURRENT_USER\software\Microsoft\Command Processor) so it's default. If there is no Autorun key, create it (it contains commands executed when cmd prompt is opened)
Start cmd prompt, then pipe output of your command to another cmd.exe, and redirect output of that to file:
more | cmd 2>nul >timestamped.log (you'd use your command where I used more). With more, entering:
this is a message
which was timestamped ^Z
produces following lines in timestamped.log (after two lines with cmd processor version info):
23:19:57,17_this is a message
23:19:59,95_which was timestamped
This works because cmd will try to execute your log entry. This fails (and error message is supressed/sent to nul), but at the same time echoes it together with prompt (time/date).
You must be very careful if your log messages are not quoted (or more generally, if you're not sure of their format, or they are not created under your direct control) - if your line happens to start with a word which is a valid command - it will be executed!

How can I echo a newline in a batch file?

How can you you insert a newline from your batch file output?
I want to do something like:
echo hello\nworld
Which would output:
hello
world
Use:
echo hello
echo:
echo world
echo hello & echo.world
This means you could define & echo. as a constant for a newline \n.
Here you go, create a .bat file with the following in it :
#echo off
REM Creating a Newline variable (the two blank lines are required!)
set NLM=^
set NL=^^^%NLM%%NLM%^%NLM%%NLM%
REM Example Usage:
echo There should be a newline%NL%inserted here.
echo.
pause
You should see output like the following:
There should be a newline
inserted here.
Press any key to continue . . .
You only need the code between the REM statements, obviously.
There is a standard feature echo: in cmd/bat-files to write blank line, which emulates a new line in your cmd-output:
#echo off
echo line1
echo:
echo line2
or
#echo line1 & echo: & echo line2
Output of cited above cmd-file:
line1
line2
Like the answer of Ken, but with the use of the delayed expansion.
setlocal EnableDelayedExpansion
(set \n=^
%=Do not remove this line=%
)
echo Line1!\n!Line2
echo Works also with quotes "!\n!line2"
First a single linefeed character is created and assigned to the \n-variable.
This works as the caret at the line end tries to escape the next character, but if this is a Linefeed it is ignored and the next character is read and escaped (even if this is also a linefeed).
Then you need a third linefeed to end the current instruction, else the third line would be appended to the LF-variable.
Even batch files have line endings with CR/LF only the LF are important, as the CR's are removed in this phase of the parser.
The advantage of using the delayed expansion is, that there is no special character handling at all.
echo Line1%LF%Line2 would fail, as the parser stops parsing at single linefeeds.
More explanations are at
SO:Long commands split over multiple lines in Vista/DOS batch (.bat) file
SO:How does the Windows Command Interpreter (CMD.EXE) parse scripts?
Edit: Avoid echo.
This doesn't answer the question, as the question was about single echo that can output multiple lines.
But despite the other answers who suggests the use of echo. to create a new line, it should be noted that echo. is the worst, as it's very slow and it can completly fail, as cmd.exe searches for a file named ECHO and try to start it.
For printing just an empty line, you could use one of
echo,
echo;
echo(
echo/
echo+
echo=
But the use of echo., echo\ or echo: should be avoided, as they can be really slow, depending of the location where the script will be executed, like a network drive.
echo. Enough said.
If you need it in a single line, use the &. For example,
echo Line 1 & echo. & echo line 3
would output as:
Line 1
line 3
Now, say you want something a bit fancier, ...
set n=^&echo.
echo hello %n% world
Outputs
hello
world
Then just throw in a %n% whenever you want a new line in an echo statement. This is more close to your \n used in various languages.
Breakdown
set n= sets the variable n equal to:
^ Nulls out the next symbol to follow:
& Means to do another command on the same line. We don't care about errorlevel(its an echo statement for crying out loud), so no && is needed.
echo. Continues the echo statement.
All of this works because you can actually create variables that are code, and use them inside of other commands. It is sort of like a ghetto function, since batch is not exactly the most advanced of shell scripting languages. This only works because batch's poor usage of variables, not designating between ints, chars, floats, strings, etc naturally.
If you are crafty, you could get this to work with other things. For example, using it to echo a tab
set t=^&echo. ::there are spaces up to the double colon
When echoing something to redirect to a file, multiple echo commands will not work. I think maybe the ">>" redirector is a good choice:
echo hello > temp
echo world >> temp
If you need to put results to a file, you can use:
(echo a & echo: & echo b) > file_containing_multiple_lines.txt
Just like Grimtron suggests - here is a quick example to define it:
#echo off
set newline=^& echo.
echo hello %newline%world
Output
C:\>test.bat
hello
world
You can also do like this,
(for %i in (a b "c d") do #echo %~i)
The output will be,
a
b
c d
Note that when this is put in a batch file, '%' shall be doubled.
(for %%i in (a b "c d") do #echo %%~i)
If anybody comes here because they are looking to echo a blank line from a MINGW make makefile, I used
#cmd /c echo.
simply using echo. causes the dreaded process_begin: CreateProcess(NULL, echo., ...) failed. error message.
I hope this helps at least one other person out there :)
Ken and Jeb solutions works well.
But the new lines are generated with only an LF character and I need CRLF characters (Windows version).
To this, at the end of the script, I have converted LF to CRLF.
Example:
TYPE file.txt | FIND "" /V > file_win.txt
del file.txt
rename file_win.txt file.txt
If one needs to use famous \n in string literals that can be passed to a variable, may write a code like in the Hello.bat script below:
#echo off
set input=%1
if defined input (
set answer=Hi!\nWhy did you call me a %input%?
) else (
set answer=Hi!\nHow are you?\nWe are friends, you know?\nYou can call me by name.
)
setlocal enableDelayedExpansion
set newline=^
rem Two empty lines above are essential
echo %answer:\n=!newline!%
This way multiline output may by prepared in one place, even in other scritpt or external file, and printed in another.
The line break is held in newline variable. Its value must be substituted after the echo line is expanded so I use setlocal enableDelayedExpansion to enable exclamation signs which expand variables on execution. And the execution substitutes \n with newline contents (look for syntax at help set). We could of course use !newline! while setting the answer but \n is more convenient. It may be passed from outside (try Hello R2\nD2), where nobody knows the name of variable holding the line break (Yes, Hello C3!newline!P0 works the same way).
Above example may be refined to a subroutine or standalone batch, used like call:mlecho Hi\nI'm your comuter:
:mlecho
setlocal enableDelayedExpansion
set text=%*
set nl=^
echo %text:\n=!nl!%
goto:eof
Please note, that additional backslash won't prevent the script from parsing \n substring.
After a sleepless night and after reading all answers herein, after reading a lot of SS64 > CMD and after a lot of try & error I found:
The (almost) Ultimate Solution
TL;DR
... for early adopters.
Important!
Use a text editor for C&P that supports Unicode, e.g. Notepad++!
Set Newline Environment Variable ...
... in the Current CMD Session
Important!
Do not edit anything between '=' and '^'! (There's a character in between though you don't see it. Neither here nor in edit mode. C&P works here.)
:: Sets newline variables in the current CMD session
set \n=​^&echo:
set nl=​^&echo:
... for the Current User
Important!
Do not edit anything between (the second) '␣' and '^'! (There's a character in between though you don't see it. Neither here nor in edit mode. C&P works here.)
:: Sets newline variables for the current user [HKEY_CURRENT_USER\Environment]
setx \n ​^&echo:
setx nl ​^&echo:
... for the Local Machine
Important!
Do not edit anything between (the second) '␣' and '^'! (There's a character in between though you don't see it. Neither here nor in edit mode. C&P works here.)
:: Sets newline variables for the local machine [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]
setx \n ​^&echo: /m
setx nl ​^&echo: /m
Why just almost?
It does not work with double-quotes that are not paired (opened and closed) in the same printed line, except if the only unpaired double-quote is the last character of the text, e.g.:
works: ""echo %\n%...after "newline". Before "newline"...%\n%...after "newline" (paired in each printed line)
works: echo %\n%...after newline. Before newline...%\n%...after newline" (the only unpaired double-quote is the last character)
doesn't work: echo "%\n%...after newline. Before newline...%\n%...after newline" (double-quotes are not paired in the same printed line)
Workaround for completely double-quoted texts (inspired by Windows batch: echo without new line):
set BEGIN_QUOTE=echo ^| set /p !="""
...
%BEGIN_QUOTE%
echo %\n%...after newline. Before newline...%\n%...after newline"
It works with completely single-quoted texts like:
echo '%\n%...after newline. Before newline...%\n%...after newline'
Added value: Escape Character
Note
There's a character after the '=' but you don't see it here but in edit mode. C&P works here.
:: Escape character - useful for color codes when 'echo'ing
:: See https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#text-formatting
set ESC=
For the colors see also https://imgur.com/a/EuNXEar and https://gist.github.com/gerib/f2562474e7ca0d3cda600366ee4b8a45.
2nd added value: Getting Unicode characters easily
A great page for getting 87,461 Unicode characters (AToW) by keyword(s): https://www.amp-what.com/.
The Reasons
The version in Ken's answer works apparently (I didn't try it), but is somehow...well...you see:
set NLM=^
set NL=^^^%NLM%%NLM%^%NLM%%NLM%
The version derived from user2605194's and user287293's answer (without anything between '=' and '^'):
set nl=^&echo:
set \n=^&echo:
works partly but fails with the variable at the beginning of the line to be echoed:
> echo %\n%Hello%\n%World!
echo & echo:Hello & echo:World!
echo is ON.
Hello
World
due to the blank argument to the first echo.
All others are more or less invoking three echos explicitely.
I like short one-liners.
The Story Behind
To prevent set \n=^&echo: suggested in answers herein echoing blank (and such printing its status) I first remembered the Alt+255 user from the times when Novell was a widely used network and code pages like 437 and 850 were used. But 0d255/0xFF is ›Ÿ‹ (Latin Small Letter Y with diaeresis) in Unicode nowadays.
Then I remembered that there are more spaces in Unicode than the ordinary 0d32/0x20 but all of them are considered whitespaces and lead to the same behaviour as ›␣‹.
But there are even more: the zero width spaces and joiners which are not considered as whitespaces. The problem with them is, that you cannot C&P them since with their zero width there's nothing to select. So, I copied one that is close to one of them, the hair space (U+200A) which is right before the zero width space (U+200B) into Notepad++, opened its Hex-Editor plugin, found its bit representation E2 80 8A and changed it to E2 80 8B. Success! I had a non-whitespace character that's not visible in my \n environment variable.
To start a new line in batch, all you have to do is add "echo[", like so:
echo Hi!
echo[
echo Hello!
why not use substring/replace space to echo;?
set "_line=hello world"
echo\%_line: =&echo;%
Results:
hello
world
Or, replace \n to echo;
set "_line=hello\nworld"
echo\%_line:\n=&echo;%
For windows 10 with virtual terminal sequences there exists the means control the cursor position to a high degree.
To define the escape sequence 0x1b, the following can be used:
#Echo off
For /f %%a in ('echo prompt $E^| cmd')Do set \E=%%a
To output a single newline Between Strings:
<nul set /p "=Hello%\E%[EWorld"
To output n newlines where n is replaced with an integer:
<nul set /p "=%\E%[nE"
Many
Please note that all solutions that use cursor positioning according to Console Virtual Terminal Sequences, Cursor Positioning with:
Sequence
Code
Description
Behaviour
ESC [ <n> E
CNL
Cursor Next Line
Cursor down <n> lines from current position
only work as long as the bottom of the console window is not reached.
At the bottom there is no space left to move the cursor down so it just moves left (with the CR of CRLF) and the line printed before is overwritten from its beginning.
To echo a newline, add a dot . right after the echo:
echo.
This worked for me, no delayed expansion necessary:
#echo off
(
echo ^<html^>
echo ^<body^>
echo Hello
echo ^</body^>
echo ^</html^>
)
pause
It writes output like this:
<html>
<body>
Hello
</body>
</html>
Press any key to continue . . .
You can use #echo ( #echo + [space] + [insecable space] )
Note: The insecable space can be obtained with Alt+0160
Hope it helps :)
[edit] Hmm you're right, I needed it in a Makefile, it works perfectly in there. I guess my answer is not adapted for batch files... My bad.
simple
set nl=.
echo hello
echo%nl%
REM without space ^^^
echo World
Result:
hello
world
Be aware, this won't work in console because it'll simulate an escape key and clear the line.
Using this code, replace <ESC> with the 0x1b escape character or use this Pastebin link:
:: Replace <ESC> with the 0x1b escape character or copy from this Pastebin:
:: https://pastebin.com/xLWKTQZQ
echo Hello<ESC>[Eworld!
:: OR
set "\n=<ESC>[E"
echo Hello%\n%world!
Adding a variant to Ken's answer, that shows setting values for environment variables with new lines in them.
We use this method to append error conditions to a string in a VAR, then at the end of all the error checking output to a file as a summary of all the errors.
This is not complete code, just an example.
#echo off
SETLOCAL ENABLEDELAYEDEXPANSION
:: the two blank lines are required!
set NLM=^
set NL=^^^%NLM%%NLM%^%NLM%%NLM%
:: Example Usage:
Set ErrMsg=Start Reporting:
:: some logic here finds an error condition and appends the error report
set ErrMsg=!ErrMsg!!NL!Error Title1!NL!Description!NL!Summary!NL!
:: some logic here finds another error condition and appends the error report
set ErrMsg=!ErrMsg!!NL!Error Title2!NL!Description!NL!Summary!NL!
:: some logic here finds another error condition and appends the error report
set ErrMsg=!ErrMsg!!NL!Error Title3!NL!Description!NL!Summary!NL!
echo %ErrMsg%
pause
echo %ErrMsg% > MyLogFile.log
Log and Screen output look like this...

Resources