Windows批处理:无新行回显

Windows批处理相当于Linux shell命令echo -n,它抑制了输出末尾的换行符?

其思想是在循环中的同一行上写入。

305803 次浏览

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

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

使用set/p参数可以不带换行符进行回显:

C:\> echo Hello World
Hello World


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

< a href = " http://www.devtrends.com/index.php/echo-without-carriage-return-or-line-feed-cr-lf/ " > < / >来源

使用:echo | set /p=<NUL set /p=都可以抑制换行符。

然而,当编写更高级的脚本时,检查ERRORLEVEL变得非常重要,因为设置set /p=而不指定变量名将把ERRORLEVEL设置为1,这可能是非常危险的。

一个更好的方法是使用一个虚拟变量名,就像这样 echo | set /p dummyName=Hello World < / p >

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

你可以使用"tr"从gnuwin32 (coreutils包)中删除换行符

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

顺便说一下,如果您正在编写大量脚本,gnuwin32是一个金矿。

简单的SET /P方法在不同的Windows版本之间有一些限制。

  • 前导引号可能被删除

  • 前导空白可能被剥离

  • =前导导致语法错误。

更多信息请参见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

下面是另一个方法,它使用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

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

窍门是你可以在DOS的文本编辑器编辑中调用的退格字符。要在EDIT中创建它,按ctrlP + ctrlH。 我想把它粘贴在这里,但是这个网页不能显示它。它在记事本上是可见的(它很奇怪,就像一个小的黑色矩形,中间有一个白圈)

你可以这样写:

<nul set /p=.9    Hello everyone
点可以是任何字符,它只是告诉SET / p文本从这里开始,在空格之前,而不是在“你好”。 “9”是一个退格字符的表示,我不能在这里显示。你必须用它来代替9,它会删除“”,之后你会得到这个:

    Hello Everyone

而不是:

Hello Everyone

我希望这对你们有帮助

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

也许这就是你要找的,这是一个老派的剧本……: 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%”使用退格符在“示例消息”之后添加空格,分隔“Pause命令的输出”,而不是在“示例消息”之后实际添加一个可见字符。然而,使用常规百分号也可以做到这一点。

作为@xmechanix回答的补充,通过将内容写入一个文件,我注意到:

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

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

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

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

将打印结尾不带换行符或空格字符的字符串。

可以使用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

通过这种方式,您可以打印任何内容而无需新行。我已经使程序打印字符一个接一个,但你也可以使用文字,而不是通过改变循环字符。

在上面的例子中,我使用了" enabledelayeexpand ",所以set /p命令不识别"!"字符,并打印一个点来代替它。我希望你不要用感叹号“!”;)

示例1:这个工作并产生退出代码= 0。这很好。 注意“。”

.

.
< p > C: \ \ phife用户。狗\ gitrepos \ 1 \ repo_abc \脚本# < br > @echo。| set /p JUNK_VAR=这是一个像Linux echo一样显示的消息-n将显示它…,回声%返回码% < / p >

这是一个像Linux echo -n一样显示的消息…0

示例2:此工作产生退出代码= 1。这很糟糕。 请注意回声后面缺少“。”。

< p > C: \ \ phife用户。狗\ gitrepos \ 1 \ repo_abc \脚本# < br > @echo | set /p JUNK_VAR=这是一个像Linux echo -n会显示它的消息…,回声%返回码% < / p >

这是一个像Linux echo -n一样显示的消息…1

在这里

<nul set /p =Testing testing

同时也从空间的使用开始呼应

echo.Message goes here

DIY cw.exe(控制台写)实用程序

如果你找不到现成的,你可以自己动手做。有了这个cw实用程序,你可以使用各种类型的字符。至少,我是这么想的。请对它进行压力测试,然后告诉我。

工具

你所需要的只是安装net,这在当今非常普遍。

材料

输入/复制粘贴了一些字符。

步骤

  1. 用以下内容创建.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. 运行它。

  2. 现在你有了一个很棒的4KB实用程序,可以删除.bat

或者,你可以在任何批处理中插入这段代码作为子例程,将结果.exe发送给%temp%,在你的批处理中使用它,当你完成时删除它。

如何使用

如果你想写一些没有新行:
cw Whatever you want, even with "", but remember to escape ^|, ^^, ^&, etc. unless double-quoted, like in "| ^ &". < / p >

如果你想要一个回车(回到行首),只需运行
cw < / p >

所以试试从命令行:

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

我根据@arnep的想法做了一个函数:

echo|set /p="Hello World"

下面就是:

:SL (sameline)
echo|set /p=%1
exit /b
call :SL "Hello There"一起使用
我知道这没什么特别的,但我花了很长时间才想出来,所以我想我应该把它贴在这里。

受到这个问题答案的启发,我制作了一个简单的计数器批处理脚本,在同一行上打印进度值(0-100%)(覆盖前一行)。也许这对寻找类似解决方案的其他人也有价值。

备注: *是不可打印的字符,应该使用[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

回显带有空格且没有换行符

如前面佩德罗所述,echo没有换行且前面有空格(提供"9"是一个真[BackSpace])。

<nul set /p=.9    Hello everyone
我在Windows 10的新控制台上遇到了一些问题,但我用下面的方法解决了 在CMD中输入:

echo .◘>bs.txt

我▲;按[Alt] + [8]
(实际符号可能因代码页而异).

然后很容易从“;bs.txt”中复制结果。使用Notepad.exe到需要的地方。

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

使用EchoX.EXE从可怕的"Shell脚本工具包"由比尔·斯图尔特 < br > 如何抑制换行在一个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

给:

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

这种用法的帮助是:

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

该实用程序小于48K,应该位于Path中。它可以做的更多事情:
-打印文本而不移动到下一行
-打印文本在一定宽度内向左、中间或右边对齐
-打印文本带有制表符、换行符和返回
-打印前景和背景颜色的文本

Toolkit还包括12个很棒的脚本编写技巧 下载页面还包含其他三个有用的工具包

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));

如果它叫write.bat,你可以这样测试它:

call write.bat string & echo _Another_String_

如果你想使用powershell,但有cmd定义的变量,你可以使用:

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

我发现这个简单的单行批处理文件叫做“echopart .bat”;非常有用。

@echo | set /p=%*

然后,我可以在交互式CMD行中,或者作为快捷方式的一部分,写如下所示的内容。它带来了一些新的可能性。

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

enter image description here

如果你在批处理文件中使用它,文本可以从参数变量而不是不可变字符串中获得。例如:

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

因此,在“sayhello .bat”中执行这一行;允许:

enter image description here

甚至……

enter image description here

玩个游戏,玩得开心!