echo multiple lines without an ending of space new line

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
taripo
Posts: 228
Joined: 01 Aug 2011 13:48

echo multiple lines without an ending of space new line

#1 Post by taripo » 10 Sep 2014 08:45

I would like to echo to the screen abc\r\ndef\r\n

Instead, I get abc{space}\r\ndef{space}\r\n

i.e. i'm getting
abc{space}
def{space}

I don't want the space(hex 20), before the new line.

Code: Select all

C:\>(echo abc&&echo def)| xxd -p
616263200d0a646566200d0a


I know set /p can give a bit more control as it doesn't add a new line, but then I can't get subsequent lines with it So i've tried..

Code: Select all

C:\>set /p=abc && set /p=def
abc

C:\>(set /p=abc) && echo. && set /p=def
abc

C:\>


so, I can't get my indended result of abc, new line, def. i'm not getting there with echo or with set /p

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: echo multiple lines without an ending of space new line

#2 Post by aGerman » 10 Sep 2014 10:15

Code: Select all

@echo off &setlocal
>"test.txt" (echo abc&echo def)
REM No spaces found in test.txt.

for /f "delims=" %%i in ('echo abc^&echo def') do echo "%%i"
REM Enclosed %%i into quotes to see if there were spaces but didn't find any.

pause

I guess that "xxd" (what is it :?:) causes the problem.

Regards
aGerman

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: echo multiple lines without an ending of space new line

#3 Post by einstein1969 » 10 Sep 2014 11:03

Hi,

when there is a pipe, the cmd insert a SPACE...

It's possible insert a LF in the set/p? I didn't ...

Code: Select all

@echo off& setlocal &Goto :Init_System

:Main

  setlocal EnableDelayedExpansion

  mode 80,43 & cls
 
  for /L %%i in (1,1,20) do (call :color 40 "             " & echo()

  mode 80,25 & echo(

  (<nul set /p .="aaa")| (set "v=" & set /p "v=" & call echo 1:'%%v%%')

  (<nul set /p .=aaa)| (set "v=" & set /p "v=" & call echo 2:'%%v%%')

  (echo aaa)|(set "v=" & set /p "v=" & call set /p ".=3:'%%v%%'" & echo()

  <nul set /p ".=aaa"| (set "v=" & set /p "v=" & call echo 4:'%%v%%')

  <nul set /p .=aaa| (set "v=" & set /p "v=" & call echo 5:'%%v%%')

  echo aaa|(set "v=" & set /p "v=" & call echo 6:'%%v%%')

  (echo aaa&& echo bbb)
  break|(echo aaa&& echo bbb)

  break|(<nul set/p=aaa& echo(& <nul set/p=bbb&echo()

  break|(<nul set/p"=aaa"& <nul set/p"=bbb")

  rem HOW INSERT LF in set /p ?????


Goto :EndMain

:: ( Begin Color Function

:color

        (echo %~2\..\'
        ) > $$$.color.txt && findstr /a:%~1 /f:$$$.color.txt "."

        Shift
        Shift

        If ""=="%~1" Goto :Eof

        goto :color

:: ) End color Fuction


:Init_system


  for /F "tokens=1,2 delims=#" %%a in (
   '"prompt #$H#$E# & echo on & for %%b in (1) do rem"'
  ) do (set "DEL=%%a")

  <nul set /p ".=%DEL%%DEL%%DEL%%DEL%%DEL%%DEL%" > "'"

Goto :Main

:EndMain
  :: Clearing all garbage
  del '
Goto :Eof



einstein1969

taripo
Posts: 228
Joined: 01 Aug 2011 13:48

Re: echo multiple lines without an ending of space new line

#4 Post by taripo » 10 Sep 2014 11:18

EDIT- einstein has just pointed out that it wasn't xxd adding it.. it was cmd, so (as I suspected.. xxd doesn't lie or add characters!).. But the rest of what I wrote addresses what you asked re what is xxd.


@agerman You're right, that is so strange.. When I | xxd it causes the problem


Code: Select all

C:\crp>(echo abc&&echo def)| xxd
0000000: 6162 6320 0d0a 6465 6620 0d0a            abc ..def ..

C:\crp>(echo abc&&echo def)|xxd
0000000: 6162 6320 0d0a 6465 6620 0d0a            abc ..def ..

Here(not piping to xxd), xxd reports it correctly

C:\crp>(echo abc&&echo def)>a.a

C:\crp>xxd a.a
0000000: 6162 630d 0a64 6566 0d0a                 abc..def..



As to what xxd is..
it's a program that reveals what is really in files.. I've no idea what happened there with | xxd but i'll give you examples of what xxd can do

Code: Select all

C:\blah>echo abc>a.a

C:\blah>type a.a
abc

C:\blah>xxd a.a
0000000: 6162 630d 0a                             abc..

C:\blah>


As above, you can use xxd to see that there is a new line after the abc

61 is hex for 'a', 0d0a is hex for the line separator that windows uses. \r\n character 13 then character 10


Suppose we open notepad and save a file as UTF-8 so Unicode as the mapping, but the particular encoding is 8 bits for characters whose unicode code is 8 bits like characters within ascii, but 16 or perhaps more, bits, for characters beyond ascii. (I think that's what UTF-8 is anyway). It's more sensible in terms of space, than UTF-16.


C:\blah>notepad.exe a.txt

write the text 'abc' in there and save it

cmd can't handle it well

Code: Select all

C:\blah>type a.txt
´╗┐abc
C:\blah>



If you want to see what is really inside the file

You can run these commands

Code: Select all

C:\blah>file a.txt
a.txt; UTF-8 Unicode (with BOM) text, with no line terminators

C:\blah>
C:\blah>xxd -p a.txt
efbbbf616263

below, each dot on the right is a character, represented by 2 nibbles(hex digits) s. ef bb bf 61 62 63  (61 62 63 are a b c)
http://www.asciitable.com/   <-- look in the hex column for 61 and 62 and 63, they're a,b,c

C:\blah>xxd a.txt
0000000: efbb bf61 6263                           ...abc

C:\blah>


I never really learnt assembly language but many years ago I found out that the instruction MOV AX,3 can be encoded with certain characters, and so I typed the equivalent characters into notepad so that they'd get translated into the correct binary. But actually it'd have been much easier with xxd.

While you can't input binary into xxd, you can input hex.

Code: Select all

C:\blah>echo 616263| xxd -r -p
abc
C:\blah>


You could do echo 616263| xxd -r -p>a.txt
then open a.txt in notepad and see abc
you can add a new line
echo 6162630d0a| xxd -r -p >a.txt

A person could write an executable file in machine code with xxd! (if they knew assembly language that is!)

Suppose you have some characters in a file and you want to know what they are.. xxd shows you the truth.. what is in the file.

xxd seems to work fine within cygwin.. it's an oddity with xxd running natively within windows.. very strange

Code: Select all

C:\cygwin>cygwin<ENTER>

$ echo -e 'a\nb' | xxd -p
610a620a

$ exit
logout
Terminate batch job (Y/N)? y

C:\cygwin\bin>(echo a&& echo b)| xxd -p
61200d0a62200d0a

C:\cygwin\bin>



When you want to find out what is going on, what is really inside a file with just DOS commands or NT commands, you need some really extreme talent with FOR and Batch like you have..

The reason why I used xxd here on this forum, was just as a tool to see what was going on with the echo..

Little did I know, the native windows xxd seems to mess up when you | to it. That is very strange!

xxd is available in cygwin, or it is an EXE that bizarrely, comes with VIM 7(so one can download vim7 and get that exe). The 'file' command which I used here when describing xxd, (which identifies file types) is available from gnuwin32 or cygwin.
Last edited by taripo on 10 Sep 2014 11:34, edited 1 time in total.

taripo
Posts: 228
Joined: 01 Aug 2011 13:48

Re: echo multiple lines without an ending of space new line

#5 Post by taripo » 10 Sep 2014 11:23

@einstein,

in time I will try to wrap my head around that batch code you mention as demonstration..

you say when there's a pipe cmd inserts a space

I've just done a simple test.. you're right. (excuse my Gnu usage, just used a command to find 'a' and replace it with 'a' but it just confirms what you said)

Code: Select all

C:\blah>(echo abc&&echo def)|sed "s/a/a/">a.a

C:\blah>xxd -p a.a
616263200d0a646566200d0a

C:\blah>


So is there anything I can do then, in batch, if I want to have new lines without the space?

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: echo multiple lines without an ending of space new line

#6 Post by einstein1969 » 10 Sep 2014 11:34

If you execute my code you see that the last example don't print the space

use the set/p with double quote

and the problem is for NEWLINE or LINEFEED( LF)

I do not know how to insert a LF in a set / p. But perhaps someone more experienced than me can do it.

taripo
Posts: 228
Joined: 01 Aug 2011 13:48

Re: echo multiple lines without an ending of space new line

#7 Post by taripo » 10 Sep 2014 11:36

@einstein yeah I know about set /p as an alternative to echo.. But doing that I had that problem that you speak of. Not getting multiple lines with set /p. I tried that in my first post but hit that problem

aGerman
Expert
Posts: 4678
Joined: 22 Jan 2010 18:01
Location: Germany

Re: echo multiple lines without an ending of space new line

#8 Post by aGerman » 10 Sep 2014 12:31

Did you try without using parentheses?

Code: Select all

@prompt $g &setlocal
rem ******1*******
for /f "delims=" %%i in ('^(echo abc^&echo def^)^|find /v ""') do rem "%%i"
rem ******2*******
for /f "delims=" %%i in ('echo abc^&echo def^|find /v ""') do rem "%%i"
pause>nul

Result:

Code: Select all

> rem ******1*******

> for /F "delims=" %i in ('(echo abc&echo def)|find /v ""') do rem "%i"

> rem "abc "

> rem "def "

> rem ******2*******

> for /F "delims=" %i in ('echo abc&echo def|find /v ""') do rem "%i"

> rem "abc"

> rem "def"

> pause1>nul

Regards
aGerman

taripo
Posts: 228
Joined: 01 Aug 2011 13:48

Re: echo multiple lines without an ending of space new line

#9 Post by taripo » 10 Sep 2014 15:00

@aGerman

without the parenthesis then both don't get sent to the pipe.


in your example, echo abc&echo def|find /v "" The echo abc isn't getting sent to the find. Without parentheses, it is grouping them like (echo abc)&echo def | find /v "".(though without the space problem). I see that from the example below, which shows why I needed parentheses.

I want both to be sent to the pipe..


Code: Select all

C:\>echo abc&echo def| find "e"
abc
def


^^^ That seems to echo abc , and then echo def| find "e", so then displays def.

So it's not sending both to the pipe. 'cos it's showing abc.

Code: Select all

C:\>(echo abc&echo def)| find "e"
def

C:\>


^^ That one sends both to the pipe, But I get the space(the 20, just prior to the new line 0d0a).

Code: Select all

C:\>(echo abc&echo def)| find "e">c:\blah\a.a

C:\>xxd -p c:\blah\a.a
646566200d0a

C:\>

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: echo multiple lines without an ending of space new line

#10 Post by jeb » 11 Sep 2014 05:33

taripo wrote:@einstein yeah I know about set /p as an alternative to echo.. But doing that I had that problem that you speak of. Not getting multiple lines with set /p. I tried that in my first post but hit that problem


It's simple

Code: Select all

setLocal EnableDelayedExpansion
set ^"LF=^

" Do not remove the blank line
set /p "=abc!LF!def" < nul


But I suppose you tried it this way

Code: Select all

...
( set /p "=abc!LF!def" < nul) | more

But this outputs only
abc!LF!def


But you can solve this by reading Why does delayed expansion fail when inside a piped block of code?

Then it's obvious :D that you can use

Code: Select all

set ^"LF=^

" Do not remove the blank line
set "caret=^"
(<nul set /p ^^"=abc%%caret%%%%LF%%%%LF%%def^" ) | more


jeb

taripo
Posts: 228
Joined: 01 Aug 2011 13:48

Re: echo multiple lines without an ending of space new line

#11 Post by taripo » 11 Sep 2014 06:09

Thanks jeb that is very interesting. I see it works in a batch file

How do you do it from the command line, outside of a batch file?

My attempt, from the command line, even at your stage 1/2, was a flop.

I did cmd /v:on

Code: Select all

C:\blah>set ^"LF=^
More? set /p "=abc!LF!def" < nul

C:\blah>echo %a%
%a%
C:\blah>echo !a!
!a!

C:\blah>



EDIT
i'm getting there!

Code: Select all

C:\blah>set ^"ASDFASDF=^
More?
More? " dfg

C:\blah>set ASDFASDF
ASDFASDF=


C:\blah>


But the funny thing is, it mixes up a *nix line ending with a windows line ending!

C:\blah>echo abc!ASDFASDF!abc>a.a

C:\blah>xxd -p a.a
6162630a6162630d0a

C:\blah>

The batch magic generated new line, uses the *nix 0a, though echo puts in the 0d0a

This deals with that..

Code: Select all

C:\blah><nul set/p= abc!ASDFASDF!abc
abc
abc
C:\blah><nul set/p= abc!ASDFASDF!abc>a.a

C:\blah>xxd -p a.a
6162630a616263

C:\blah>


But The windows \r\n is I think meant to be a line separator so it doesn't go at the end of the last line. The unix one \n is meant to be a line terminator so it'd go after every line

so that deals with that, putting the 0a at the end of the last line

Code: Select all

C:\blah><nul set/p= abc!ASDFASDF!abc!ASDFASDF!>a.a

C:\blah>xxd -p a.a
6162630a6162630a

C:\blah>


Perhaps though given that this is windows the question should be asked..

Can that technique be used to generate a Windows line separator (\r\n) rather than a unix line terminator (\n) ?
Last edited by taripo on 11 Sep 2014 06:58, edited 3 times in total.

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: echo multiple lines without an ending of space new line

#12 Post by einstein1969 » 11 Sep 2014 06:20

jeb wrote:

Code: Select all

setLocal EnableDelayedExpansion
set ^"LF=^

" Do not remove the blank line
set /p "=abc!LF!def" < nul




Hi Jeb,

why there is necessity of escape with the caret the first double quote?

Is the same?

Code: Select all

(set LF=^

)


where i find info on the LF generating? How to practice?

thanks , einstein1969

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: echo multiple lines without an ending of space new line

#13 Post by jeb » 11 Sep 2014 07:22

einstein1969 wrote:why there is necessity of escape with the caret the first double quote?

I copied this technic from Dave, it uses quotes, but therefore you need to escape the first quote so the line ending caret will work (else it would be treated as normal character).

Normally I used this, but it requires two empty lines

Code: Select all

SET LF=^


REM ** Two empty lines are required **


einstein1969 wrote:Is the same?
Code:
(set LF=^

)

Your version works too, as it's only necessary that a multiline caret is followed by two linefeeds and then it should be ensured that no other characters are appended.
Your version is parsed to "set LF=^<LF><LF>" as the brackets are not part of the line.

Like here

Code: Select all

setlocal EnableDelayedExpansion
set Fail=^

REM Two linefeeds but this line will be appended
echo !fail!


I would prefere a version without the problem that an unvisible space will break the code ...

taripo
Posts: 228
Joined: 01 Aug 2011 13:48

Re: echo multiple lines without an ending of space new line

#14 Post by taripo » 11 Sep 2014 08:08

Is there a way to get a CRLF there(what windows uses) instead of just an LF(what *nix uses)?

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: echo multiple lines without an ending of space new line

#15 Post by jeb » 12 Sep 2014 01:34

Yes, you could create a CR also.

Code: Select all

for /F "usebackq" %%a in (`copy /Z "%~dpf0" nul`) DO (
   set "cr=%%a"
)


But a CR can only be used with delayed expansion (without any exception).

So it's hard to use it inside a piped blocked.

But with a normal set/p it's easy

Code: Select all

setlocal EnableDelayedExpansion
set ^"LF=^

" Do not remove the blank line
::: CR should  be used only with DelayedExpansion
for /F "usebackq" %%a in (`copy /Z "%~dpf0" nul`) DO (
   set "cr=%%a"
)
<nul set /p "=abc!CR!!LF!def" > a.txt

Post Reply