简体   繁体   English

Windows 批处理:echo 没有换行

[英]Windows batch: echo without new line

What is the Windows batch equivalent of the Linux shell command echo -n which suppresses the newline at the end of the output?什么是 Linux shell 命令echo -n的 Windows 批处理等效项,它在输出的末尾抑制换行符?

The idea is to write on the same line inside a loop.这个想法是在循环内的同一行上写。

Using set and the /p parameter you can echo without newline:使用set/p参数,您可以在没有换行符的情况下进行回显:

C:\> echo Hello World
Hello World

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

Source 来源

Using: echo | set /p=使用: echo | set /p= echo | set /p= or <NUL set /p= will both work to suppress the newline. echo | set /p=<NUL set /p=都可以抑制换行符。

However, this can be very dangerous when writing more advanced scripts when checking the ERRORLEVEL becomes important as setting set /p= without specifying a variable name will set the ERRORLEVEL to 1.但是,在检查 ERRORLEVEL 变得重要时编写更高级的脚本时,这可能非常危险,因为设置set /p=而不指定变量名称会将 ERRORLEVEL 设置为 1。

A better approach would be to just use a dummy variable name like so:更好的方法是只使用一个虚拟变量名称,如下所示:
echo | set /p dummyName=Hello World

This will produce exactly what you want without any sneaky stuff going on in the background as I had to find out the hard way, but this only works with the piped version;这将产生您想要的内容,而不会在后台发生任何偷偷摸摸的事情,因为我必须找出困难的方法,但这仅适用于管道版本; <NUL set /p dummyName=Hello will still raise the ERRORLEVEL to 1. <NUL set /p dummyName=Hello仍会将 ERRORLEVEL 提高到 1。

The simple SET /P method has limitations that vary slightly between Windows versions.简单的 SET /P 方法的局限性在 Windows 版本之间略有不同。

  • Leading quotes may be stripped前导引号可能会被删除

  • Leading white space may be stripped前导空白可能会被剥离

  • Leading = causes a syntax error.前导=导致语法错误。

See http://www.dostips.com/forum/viewtopic.php?f=3&t=4209 for more information.有关更多信息,请参阅http://www.dostips.com/forum/viewtopic.php?f=3&t=4209

jeb posted a clever solution that solves most of the problems at Output text without linefeed, even with leading space or = I've refined the method so that it can safely print absolutely any valid batch string without the new line, on any version of Windows from XP onward. jeb 发布了一个聪明的解决方案,它解决了在没有换行的情况下输出文本中的大多数问题,即使有前导空格或 =我已经改进了该方法,以便它可以在任何版本的 Windows 上安全地打印绝对没有新行的任何有效批处理字符串从 XP 开始。 Note that the :writeInitialize method contains a string literal that may not post well to the site.请注意, :writeInitialize方法包含可能无法很好地发布到站点的字符串文字。 A remark is included that describes what the character sequence should be.包含的注释描述了字符序列应该是什么。

The :write and :writeVar methods are optimized such that only strings containing troublesome leading characters are written using my modified version of jeb's COPY method. :write:writeVar方法经过优化,因此只使用我修改过的 jeb 的 COPY 方法版本写入包含麻烦的前导字符的字符串。 Non-troublesome strings are written using the simpler and faster SET /P method.使用更简单、更快的 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

As an addendum to @xmechanix's answer, I noticed through writing the contents to a file:作为@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.这将在打印的 string 末尾添加一个额外的空格,这可能很不方便,特别是因为我们试图避免在字符串末尾添加新行(另一个空格字符)。

Fortunately, quoting the string to be printed, ie 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: SET /P 中去除空白的解决方案:

the trick is that backspace char which you can summon in the text editor EDIT for DOS.诀窍是,退格字符,你可以在文本编辑器编辑DOS召唤。 To create it in EDIT press ctrlP+ctrlH .要在 EDIT 中创建它,请按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 ".点可以是任何字符,它只是告诉 SET /P 文本从那里开始,在空格之前,而不是在“ Hello ”处。 The " 9 " is a representation of the backspace char that I can't display here. 9 ”是我无法在此处显示的退格字符的表示。 You have to put it instead of the 9, and it will delete the " . " , after which you'll get this:你必须把它而不是 9,它会删除“ . ”,之后你会得到这个:

    Hello Everyone

instead of:代替:

Hello Everyone

I hope it helps我希望它有帮助

You can remove the newline using "tr" from gnuwin32 ( coreutils package)您可以使用 gnuwin32( coreutils包)中的“tr”删除换行符

@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.顺便说一句,如果您正在编写大量脚本,gnuwin32 是一个金矿。

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.这是另一种方法,它使用具有 -NoNewLine 参数的 Powershell Write-Host,将其与start /b结合使用,并提供与批处理相同的功能。

NoNewLines.cmd 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.下面的这个略有不同,不像 OP 想要的那样工作,但很有趣,因为每个结果都覆盖了模拟计数器的前一个结果。

@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

DIY cw.exe (console write) utility DIY cw.exe (控制台写入)实用程序

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.使用此cw实用程序,您可以使用各种字符。 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.您只需要安装.NET ,这在当今非常普遍。

Materials材料

Some characters typed/copy-pasted.输入/复制粘贴的一些字符。

Steps脚步

  1. Create .bat file with the following content.使用以下内容创建.bat文件。
/* >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 .现在您有一个不错的 4KB 实用程序,因此您可以删除.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.或者,您可以将此代码作为任何批处理中的子例程插入,将生成的.exe发送到%temp% ,在批处理中使用它并在完成后将其删除。

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:我根据@arnep 的想法做了一个函数:

echo|set /p="Hello World" echo|set /p="Hello World"

here it is:这里是:

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

Use it with call :SL "Hello There"将其与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.我知道这没什么特别的,但我花了很长时间才想到它,我想我会把它贴在这里。

From here这里

<nul set /p =Testing testing

and also to echo beginning with spaces use并且还以空格开头的 echo 使用

echo.Message goes here

Maybe this is what your looking for, it's a old school script... :P也许这就是你要找的,这是一个老派的剧本......: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 "."您可以通过删除“。”之后的“%bs%”来试验这个。 sign and also by spacing out the other "%bs%" after the "Example message".签名并在“示例消息”之后隔开另一个“%bs%”。

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.如您所见,“%bs%”代表退格。 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".第二个“%bs%”使用退格键在“示例消息”之后添加空格来分隔“暂停命令的输出”,而实际上并未在“示例消息”之后添加可见字符。 However, this is also possible with a regular percentage sign.但是,这也可以使用常规百分比符号。

Sample 1: This works and produces Exit code = 0. That is Good.示例 1:这有效并产生退出代码 = 0。那很好。 Note the "."注意“.” , directly after echo. , 直接在 echo 之后。

C:\\Users\\phife.dog\\gitrepos\\1\\repo_abc\\scripts # 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% set /p JUNK_VAR=这是一条显示的消息,就像 Linux echo -n 会显示它...... & echo %ERRORLEVEL%

This is a message displayed like Linux echo -n would display it ... 0这是一条显示的消息,就像 Linux echo -n 会显示它... 0

Sample 2: This works but produces Exit code = 1. That is Bad.示例 2:这有效,会产生退出代码 = 1。这是错误的。 Please note the lack of ".", after echo.请注意在 echo 之后缺少“.”。 That appears to be the difference.这似乎就是区别。

C:\\Users\\phife.dog\\gitrepos\\1\\repo_abc\\scripts # 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% set /p JUNK_VAR=这是一条显示的消息,就像 Linux echo -n 会显示它...... & echo %ERRORLEVEL%

This is a message displayed like Linux echo -n would display it ... 1这是一条显示的消息,就像 Linux echo -n 会显示它... 1

Inspired by the answers to this question, I made a simple counter batch script that keeps printing the progress value (0-100%) on the same line (overwritting the previous one).受到这个问题的答案的启发,我制作了一个简单的计数器批处理脚本,在同一行上不断打印进度值 (0-100%)(覆盖前一个)。 Maybe this will also be valuable to others looking for a similar solution.也许这对于寻找类似解决方案的其他人也很有价值。

Remark : The * are non-printable characters, these should be entered using [ Alt + Numpad 0 + Numpad 8 ] key combination, which is the backspace character.备注*是不可打印的字符,应使用 [ Alt + Numpad 0 + Numpad 8 ] 组合键输入,即backspace字符。

@ECHO OFF

FOR /L %%A in (0, 10, 100) DO (     
    ECHO|SET /P="****%%A%%"    
    CALL:Wait 1
)

GOTO:EOF

:Wait
SET /A "delay=%~1+1"
CALL PING 127.0.0.1 -n %delay% > NUL
GOTO:EOF

You can suppress the new line by using the set /p command.您可以使用 set /p 命令取消新行。 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. set /p 命令无法识别空格,为此您可以使用点和退格字符使其识别。 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 "!"在上面的示例中,我使用了“enabledelayedexpansion”,因此 set /p 命令无法识别“!” character and prints a dot instead of that.字符并打印一个点而不是那个。 I hope that you don't have the use of the exclamation mark "!"我希望你没有使用感叹号“!” ;) ;)

Use EchoX.EXE from the terrific "Shell Scripting Toolkit" by Bill Stewart使用比尔·斯图尔特( Bill Stewart)出色的“Shell Scripting Toolkit”中的 EchoX.EXE
How to suppress the linefeed in a Windows Cmd script:如何在 Windows Cmd 脚本中取消换行:

@Echo Off
Rem Print three Echos in one line of output
EchoX -n "Part 1 - "
EchoX -n "Part 2 - "
EchoX    "Part 3"
Rem

gives:给出:

Part 1 - Part 2 - Part 3
{empty line}
d:\Prompt>

The help for this usage is:这种用法的帮助是:

Usage: echox [-n] message
  -n       Do not skip to the next line.
  message  The text to be displayed.

The utility is smaller than 48K, and should live in your Path.该实用程序小于 48K,应该存在于您的路径中。 More things it can do:它可以做的更多事情:
- print text without moving to the next line - 打印文本而不移动到下一行
- print text justified to the left, center, or right, within a certain width - 在一定宽度内打印向左、居中或向右对齐的文本
- print text with Tabs, Linefeeds, and Returns - 打印带有制表符、换行符和回车符的文本
- print text in foreground and background colors - 以前景色和背景色打印文本

The Toolkit includes twelve more great scripting tricks.该工具包包括另外十二个很棒的脚本技巧。
The download page also hosts three other useful tool packages.下载页面还包含其他三个有用的工具包。

方法如下: <nul set /p="Your Text"

Echo with preceding space and without newline带有前面的空格且不带换行符的回显

As stated by Pedro earlier, echo without new line and with preceding space works (provided "9" is a true [BackSpace]).正如Pedro之前所说, echo 没有换行并且前面有空格(前提是 "9" 是一个真正的 [BackSpace])。

<nul set /p=.9    Hello everyone

I had some issues getting it to work in Windows 10 with the new console but managed the following way.我在使用新控制台在 Windows 10 中使用它时遇到了一些问题,但通过以下方式进行了管理。
In CMD type:在 CMD 类型中:

echo .◘>bs.txt

I got "◘" by pressing [Alt] + [8]按 [Alt] + [8] 得到“◘”
(the actual symbol may vary depending upon codepage). (实际符号可能因代码页而异)。

Then it's easy to copy the result from "bs.txt" using Notepad.exe to where it's needed.然后很容易使用 Notepad.exe 将结果从“bs.txt”复制到需要的地方。

@echo off
<nul set /p "_s=.◘    Hello everyone"
echo: here

With jscript:使用 jscript:

@if (@X)==(@Y) @end /*
    @cscript //E:JScript //nologo "%~nx0" %*
    @exit /b %errorlevel%
*/if(WScript.Arguments.Count()>0) WScript.StdOut.Write(WScript.Arguments.Item(0));

if it is called write.bat you can test it like:如果它被称为 write.bat 你可以像这样测试它:

call write.bat string & echo _Another_String_

If you want to use powershell but with cmd defined variables you can use:如果您想使用 powershell 但使用 cmd 定义的变量,您可以使用:

set str=_My_StrinG_
powershell "Write-Host -NoNewline ""%str%""""  & echo #Another#STRING#

I found this simple one-line batch file called "EchoPart.bat" to be quite useful.我发现这个名为“EchoPart.bat”的简单单行批处理文件非常有用。

@echo | set /p=%*

I could then write something like the line below even on an interactive CMD line, or as part of a shortcut.然后我甚至可以在交互式 CMD 行上或作为快捷方式的一部分编写类似下面的内容。 It opens up a few new possibilities.它开辟了一些新的可能性。

echopart "Hello, " & echopart "and then " & echo Goodbye

在此处输入图片说明

And if you're using it in batch files, the texts can be got from parameter variables instead of immutable strings.如果您在批处理文件中使用它,则可以从参数变量而不是不可变字符串中获取文本。 For instance:例如:

@echopart Hello %* & @echo , how are you?

So that executing this line in "SayHello.bat" allows:因此,在“SayHello.bat”中执行这一行允许:

在此处输入图片说明

or even...甚至...

在此处输入图片说明

Have a play, and have fun!玩得开心,玩得开心!

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.迟到的答案,但对于任何需要将特殊字符写入一行的人来说,他们发现dbenham的答案太长了大约 80 行,并且在简单地使用set /p的限制下,他们的脚本可能会中断(可能是由于用户输入) set /p ,将您的 .bat 或 .cmd 与编译的 C++ 或 C 语言可执行文件配对,然后只是coutprintf字符,这可能是最简单的。 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.如果您显示某种进度条或使用字符的东西,这也将允许您轻松地多次写入一行,就像 OP 显然那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM