IT story

Windows 배치 : 줄 바꿈없이 에코

hot-time 2020. 5. 1. 08:09
반응형

Windows 배치 : 줄 바꿈없이 에코


echo -n출력이 끝날 때 줄 바꿈을 억제하는 Linux 셸 명령과 동등한 Windows 배치는 무엇입니까 ?

아이디어는 루프 내에서 같은 줄에 쓰는 것입니다.


개행없이 에코 set/p매개 변수를 사용하여 :

C:\> echo Hello World
Hello World

C:\> echo|set /p="Hello World"
Hello World
C:\>

출처


사용 : echo | set /p=또는 <NUL set /p=둘 다 줄 바꿈을 억제합니다.

그러나 set /p=변수 이름을 지정하지 않고 설정하면 ERRORLEVEL이 1로 설정되므로 ERRORLEVEL을 확인할 때 고급 스크립트를 작성할 때 매우 위험 할 수 있습니다 .

더 좋은 방법은 더미 변수 이름을 다음과 같이 사용하는 것입니다.
echo | set /p dummyName=Hello World

이것은 어려운 방법을 찾아야했기 때문에 배경에서 교활한 물건을 사용하지 않고 원하는 것을 정확하게 생성하지만 파이프 버전에서만 작동합니다. <NUL set /p dummyName=Hello여전히 ERRORLEVEL을 1로 올립니다.


간단한 SET / P 방법에는 Windows 버전마다 약간의 제한이 있습니다.

  • 선행 인용 부호가 제거 될 수 있습니다

  • 선행 공백이 제거 될 수 있습니다.

  • 선행 =구문 오류가 발생합니다.

자세한 내용은 http://www.dostips.com/forum/viewtopic.php?f=3&t=4209 를 참조하십시오.

jeb는 선행 공백이 있더라도 줄 바꿈없이 출력 텍스트 의 대부분의 문제를 해결하는 영리한 솔루션을 게시했습니다. 또는 모든 버전의 Windows에서 줄 바꿈없이 유효한 배치 문자열을 안전하게 인쇄 할 수 있도록 방법을 개선했습니다. XP부터. :writeInitialize메서드에는 사이트에 제대로 게시되지 않을 수있는 문자열 리터럴이 포함되어 있습니다. 문자 순서가 무엇인지 설명하는 설명이 포함되어 있습니다.

:write:writeVar방법은 번잡 한 최고의 문자가 포함 된 문자열 만이 젭의 COPY 방법의 내 수정 된 버전을 사용하여 작성되도록 최적화되어 있습니다. 까다 롭지 않은 문자열은 더 간단하고 빠른 SET / P 방법을 사용하여 작성됩니다.

@echo off
setlocal disableDelayedExpansion
call :writeInitialize
call :write "=hello"
call :write " world!%$write.sub%OK!"
echo(
setlocal enableDelayedExpansion
set lf=^


set "str= hello!lf!world^!!!$write.sub!hello!lf!world"
echo(
echo str=!str!
echo(
call :write "str="
call :writeVar str
echo(
exit /b

:write  Str
::
:: Write the literal string Str to stdout without a terminating
:: carriage return or line feed. Enclosing quotes are stripped.
::
:: This routine works by calling :writeVar
::
setlocal disableDelayedExpansion
set "str=%~1"
call :writeVar str
exit /b


:writeVar  StrVar
::
:: Writes the value of variable StrVar to stdout without a terminating
:: carriage return or line feed.
::
:: The routine relies on variables defined by :writeInitialize. If the
:: variables are not yet defined, then it calls :writeInitialize to
:: temporarily define them. Performance can be improved by explicitly
:: calling :writeInitialize once before the first call to :writeVar
::
if not defined %~1 exit /b
setlocal enableDelayedExpansion
if not defined $write.sub call :writeInitialize
set $write.special=1
if "!%~1:~0,1!" equ "^!" set "$write.special="
for /f delims^=^ eol^= %%A in ("!%~1:~0,1!") do (
  if "%%A" neq "=" if "!$write.problemChars:%%A=!" equ "!$write.problemChars!" set "$write.special="
)
if not defined $write.special (
  <nul set /p "=!%~1!"
  exit /b
)
>"%$write.temp%_1.txt" (echo !str!!$write.sub!)
copy "%$write.temp%_1.txt" /a "%$write.temp%_2.txt" /b >nul
type "%$write.temp%_2.txt"
del "%$write.temp%_1.txt" "%$write.temp%_2.txt"
set "str2=!str:*%$write.sub%=%$write.sub%!"
if "!str2!" neq "!str!" <nul set /p "=!str2!"
exit /b


:writeInitialize
::
:: Defines 3 variables needed by the :write and :writeVar routines
::
::   $write.temp - specifies a base path for temporary files
::
::   $write.sub  - contains the SUB character, also known as <CTRL-Z> or 0x1A
::
::   $write.problemChars - list of characters that cause problems for SET /P
::      <carriageReturn> <formFeed> <space> <tab> <0xFF> <equal> <quote>
::      Note that <lineFeed> and <equal> also causes problems, but are handled elsewhere
::
set "$write.temp=%temp%\writeTemp%random%"
copy nul "%$write.temp%.txt" /a >nul
for /f "usebackq" %%A in ("%$write.temp%.txt") do set "$write.sub=%%A"
del "%$write.temp%.txt"
for /f %%A in ('copy /z "%~f0" nul') do for /f %%B in ('cls') do (
  set "$write.problemChars=%%A%%B    ""
  REM the characters after %%B above should be <space> <tab> <0xFF>
)
exit /b

@xmechanix의 답변에 대한 부록으로 파일에 내용을 쓰는 것으로 나타났습니다.

echo | set /p dummyName=Hello World > somefile.txt

That this will add an extra space at the end of the printed string, which can be inconvenient, specially since we're trying to avoid adding a new line (another whitespace character) to the end of the string.

Fortunately, quoting the string to be printed, i.e. using:

echo | set /p dummyName="Hello World" > somefile.txt

Will print the string without any newline or space character at the end.


A solution for the stripped white space in SET /P:

the trick is that backspace char which you can summon in the text editor EDIT for DOS. To create it in EDIT press ctrlP+ctrlH. I would paste it here but this webpage can't display it. It's visible on Notepad though (it's werid, like a small black rectangle with a white circle in the center)

So you write this:

<nul set /p=.9    Hello everyone

The dot can be any char, it's only there to tell SET /P that the text starts there, before the spaces, and not at the "Hello". The "9" is a representation of the backspace char that I can't display here. You have to put it instead of the 9, and it will delete the "." , after which you'll get this:

    Hello Everyone

instead of:

Hello Everyone

I hope it helps


You can remove the newline using "tr" from gnuwin32 (coreutils package)

@echo off
set L=First line
echo %L% | tr -d "\r\n"
echo Second line
pause

By the way, if you are doing lots of scripting, gnuwin32 is a goldmine.


Here is another method, it uses Powershell Write-Host which has a -NoNewLine parameter, combine that with start /b and it offers the same functionality from batch.

NoNewLines.cmd

@ECHO OFF
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 1 - ';Write-Host -NoNewLine 'Result 2 - ';Write-Host -NoNewLine 'Result 3 - '"
PAUSE

Output

Result 1 - Result 2 - Result 3 - Press any key to continue . . .

This one below is slightly different, doesn't work exactly like the OP wants, but is interesting because each result overwrites the previous result emulating a counter.

@ECHO OFF
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 1 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 2 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 3 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 4 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 5 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 6 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 7 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 8 - '"
start /b /wait powershell.exe -command "Write-Host -NoNewLine 'Result 9 - '"
PAUSE

From here

<nul set /p =Testing testing

and also to echo beginning with spaces use

echo.Message goes here

Maybe this is what your looking for, it's a old school script... :P

set nl=^& echo. 
echo %nl%The%nl%new%nl%line%nl%is%nl%not%nl%apparent%nl%throughout%nl%text%nl%
echo only in prompt.
pause

or maybe your trying to replace a current line instead of writing to a new line? you can experiment with this by removing the "%bs%" after the "." sign and also by spacing out the other "%bs%" after the "Example message".

for /f %%a in ('"prompt $H&for %%b in (1) do rem"') do set "bs=%%a"
<nul set /p=.%bs%         Example message         %bs%
pause

I find this really interesting because it uses a variable for a purpose other than what it is intended to do. as you can see the "%bs%" represents a backspace. The second "%bs%" uses the backspace to add spaces after the "Example message" to separate the "Pause command's output" without actually adding a visible character after the "Example message". However, this is also possible with a regular percentage sign.


DIY cw.exe (console write) utility

If you don't find it out-of-the-box, off-the-shelf, you can DIY. With this cw utility you can use every kind of characters. At least, I'd like to think so. Please stress-test it and let me know.

Tools

All you need is .NET installed, which is very common nowadays.

Materials

Some characters typed/copy-pasted.

Steps

  1. Create .bat file with the following content.
/* >nul 2>&1

@echo off
setlocal

set exe=cw
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*csc.exe"') do set "csc=%%v"

"%csc%" -nologo -out:"%exe%.exe" "%~f0"

endlocal
exit /b %errorlevel%

*/

using System;

namespace cw {
    class Program {
        static void Main() {
            var exe = Environment.GetCommandLineArgs()[0];
            var rawCmd = Environment.CommandLine;
            var line = rawCmd.Remove(rawCmd.IndexOf(exe),exe.Length).TrimStart('"');
            line = line.Length < 2 ? "\r" : line.Substring(2) ;
            Console.Write(line);
        }
    }
}
  1. Run it.

  2. Now you have a nice 4KB utility so you can delete the .bat.

Alternatively, you can insert this code as a subroutine in any batch, send the resulting .exe to %temp%, use it in your batch and delete it when you're done.

How to use

If you want write something without new line:
cw Whatever you want, even with "", but remember to escape ^|, ^^, ^&, etc. unless double-quoted, like in "| ^ &".

If you want a carriage return (going to the beginning of the line), run just
cw

So try this from command line:

for /l %a in (1,1,1000) do @(cw ^|&cw&cw /&cw&cw -&cw&cw \&cw)

I made a function out of @arnep 's idea:

echo|set /p="Hello World"

here it is:

:SL (sameline)
echo|set /p=%1
exit /b

Use it with call :SL "Hello There"
I know this is nothing special but it took me so long to think of it I figured I'd post it here.


Sample 1: This works and produces Exit code = 0. That is Good. Note the "." , directly after echo.

C:\Users\phife.dog\gitrepos\1\repo_abc\scripts #
@echo.| set /p JUNK_VAR=This is a message displayed like Linux echo -n would display it ... & echo %ERRORLEVEL%

This is a message displayed like Linux echo -n would display it ... 0

Sample 2: This works but produces Exit code = 1. That is Bad. Please note the lack of ".", after echo. That appears to be the difference.

C:\Users\phife.dog\gitrepos\1\repo_abc\scripts #
@echo | set /p JUNK_VAR=This is a message displayed like Linux echo -n would display it ... & echo %ERRORLEVEL%

This is a message displayed like Linux echo -n would display it ... 1


I believe there's no such option. Alternatively you can try this

set text=Hello
set text=%text% world
echo %text%

Late answer here, but for anyone who needs to write special characters to a single line who find dbenham's answer to be about 80 lines too long and whose scripts may break (perhaps due to user-input) under the limitations of simply using set /p, it's probably easiest to just to pair your .bat or .cmd with a compiled C++ or C-language executable and then just cout or printf the characters. This will also allow you to easily write multiple times to one line if you're showing a sort of progress bar or something using characters, as OP apparently was.


You can suppress the new line by using the set /p command. The set /p command does not recognize a space, for that you can use a dot and a backspace character to make it recognize it. You can also use a variable as a memory and store what you want to print in it, so that you can print the variable instead of the sentence. For example:

@echo off
setlocal enabledelayedexpansion
for /f %%a in ('"prompt $H & for %%b in (1) do rem"') do (set "bs=%%a")
cls
set "var=Hello World! :)"
set "x=0"

:loop
set "display=!var:~%x%,1!"
<nul set /p "print=.%bs%%display%"
ping -n 1 localhost >nul
set /a "x=%x% + 1"
if "!var:~%x%,1!" == "" goto end
goto loop

:end
echo.
pause
exit

In this way you can print anything without a new line. I have made the program to print the characters one by one, but you can use words too instead of characters by changing the loop.

In the above example I used "enabledelayedexpansion" so the set /p command does not recognize "!" character and prints a dot instead of that. I hope that you don't have the use of the exclamation mark "!" ;)

참고URL : https://stackoverflow.com/questions/7105433/windows-batch-echo-without-new-line

반응형