Windows批处理:回显没有新行

什么是等同于Linux shell命令的Windows批处理命令echo -n在输出结尾处抑制换行符?

这个想法是写在一个循环内的同一行。

使用set/p参数可以在不换行的情况下进行回显:

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

资源

使用: echo | set /p= echo | set /p=或者<NUL set /p=都可以用来压制换行符。

但是,在编写更高级的脚本时,如果检查ERRORLEVEL变得重要,这会非常危险,因为设置set /p=而不指定变量名称会将ERRORLEVEL设置为1。

更好的方法是只使用一个虚拟变量名称,如下所示:
echo | set /p dummyName=Hello World

这将产生正是你想要的,没有任何偷偷摸摸的东西在后台进行,因为我必须找出困难的方式,但这只适用于管道版本; <NUL set /p dummyName=Hello仍然会将ERRORLEVEL提升为1。

简单的SET / P方法具有Windows版本之间稍有不同的限制。

  • 领先报价可能被剥夺

  • 领先的白色空间可能被剥离

  • Leading =导致语法错误。

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

jeb发布了一个聪明的解决方案,它解决了输出文本中的大部分问题,即使是前导空格或者我已经改进了方法,以便在任何版本的Windows上都可以安全地打印任何有效的批处理字符串从XP开始。 请注意:writeInitialize方法包含一个字符串文字,可能不能很好地发布到网站。 包括一个说明字符序列应该是什么。

:write :writeVar方法被优化,只有使用我修改后的jeb的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 

SET / P中的剥离空白区域的解决方案:

诀窍是你可以在文本编辑器编辑 DOS中使用的退格字符。 在编辑中创建它按ctrlP + ctrlH 。 我会粘贴在这里,但这个网页无法显示它。 它在记事本上是可见的(虽然它比较小,就像一个黑色的小矩形,中间有一个白色圆圈)

所以你写这个:

 <nul set /p=.9 Hello everyone 

点可以是任何字符,只是在那里告诉SET / P文本在空格前面,而不是在“ Hello ”处。 “ 9 ”表示退格字符,我不能在这里显示。 你必须把它,而不是9,它会删除“ ”,之后你会得到这个:

  Hello Everyone 

代替:

 Hello Everyone 

我希望它有帮助

您可以使用gnuwin32( coreutils包)中的“tr”来删除换行符

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

顺便说一句,如果你正在做很多脚本,gnuwin32是一个金矿。

作为@ xmechanix答案的附录,我注意到通过将内容写入文件:

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

这将在打印的字符串的末尾添加额外的空间 ,这可能是不方便的,特别是因为我们试图避免在字符串的末尾添加新行(另一个空白字符)。

幸运的是,引用要打印的字符串,即使用:

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

将在最后打印没有任何换行符或空格字符的字符串。

这里是另一种方法,它使用Powershell Write-Host(具有-NoNewLine参数),将其与start /b结合起来,并提供与批处理相同的功能。

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 

产量

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

下面的这个稍有不同,不像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 

也许这就是你要找的,这是一个老学校的脚本…: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 

或者也许你试图取代当前的行,而不是写一个新的行? 您可以通过在“。”之后删除“%bs%”来试验。 也可以在“示例消息”之后将其他“%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 

我觉得这很有趣,因为它使用一个变量来达到目的以外的目的。 正如你所看到的“%bs%”代表退格。 第二个“%bs%”使用退格符在“示例消息”之后添加空格,以便在“示例消息”之后实际上不添加可见字符来分隔“暂停命令的输出”。 但是,这也可以用正则百分比符号来表示。

我相信没有这样的选择。 或者,你可以试试这个

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

但是对于那些需要写一些特殊字符的人来说,在简单使用set /p的限制下, dbenham的答案大概有80行太长,而且脚本可能会因为用户输入而断裂set /p ,只需将.bat或.cmd与编译的C ++或C语言可执行文件配对,然后只是coutprintf字符就可能是最简单的。 这也可以让你很容易地写多行到一行,如果你正在显示一个进度条或使用字符的东西,正如OP显然是。

您可以使用set / p命令来禁止新行。 set / p命令不能识别空格,因为您可以使用点和退格字符来识别它。 您也可以使用变量作为内存并存储您想要打印的内容,以便您可以打印变量而不是句子。 例如:

 @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 

用这种方法你可以打印任何东西而不用换行。 我已经让程序逐个打印字符,但是通过改变循环,也可以使用字符而不是字符。

在上面的例子中我使用了“enabledelayedexpansion”,所以set / p命令不能识别“!” 字符并打印一个点而不是那个。 我希望你没有使用感叹号“!” ;)

您可以使用替代命令printf或打印并使用回车来实现此目的

例如:printf“Hello World \ r”

完整的语法如下: http : //wiki.bash-hackers.org/commands/builtin/printf